Référence CLI¶
Toutes les commandes disponibles via grimoire [commande].
Auto-complétion
Installez l'auto-complétion : grimoire completion install --shell bash (ou zsh, fish).
Raccourcis
Des aliases courts sont disponibles : i=init, d=doctor, s=status, v=validate, l=lint, ck=check, u=up, c=config, r=registry.
Commandes principales¶
grimoire init¶
Initialise un nouveau projet Grimoire.
| Option | Description | Défaut |
|---|---|---|
--name TEXT |
Nom du projet | Nom du répertoire |
--archetype, -a |
Archétype d'agents | minimal |
--backend, -b |
Backend mémoire (auto, local, lexical, qdrant-local, qdrant-server, weaviate-server, mempalace, ollama) |
auto |
--memory-profile, -m |
Composition mémoire : lexical, standard, graphe, complet |
déduite |
--memory-collection TEXT |
Nom explicite de la collection, pour un backend partagé | déduit du nom du projet |
--force, -f |
Écraser la config existante | false |
--dry-run |
Afficher le plan sans écrire | false |
--output, -o |
Format de sortie : text ou json |
text |
La mémoire se choisit comme une composition, pas comme un backend : le profil fixe les sept couches du Memory OS d'un coup (mémoire courte, sémantique, sidecar structuré, graphes, mémoire chaude, visualisation).
--backend auto (le défaut, y compris avec -y) n'attache jamais
silencieusement le projet à un service mémoire trouvé sur la machine : il
résout toujours vers lexical, isolé, et se contente de signaler dans le
rapport ce qui a été détecté (issue #496). Sur un backend partagé choisi
explicitement, la collection est nommée d'après le projet (son slug) ; pour
s'attacher à une collection déjà peuplée, --memory-collection est requis. Voir
Système de mémoire.
| Profil | Composition |
|---|---|
lexical |
BM25 SQLite seul — aucun modèle, aucun service, aucun réseau |
standard |
Sémantique + BM25 fusionnés (RRF) et sidecar structuré |
graphe |
Standard + graphes Neo4j : connaissances, souvenirs, code, tâches |
complet |
Graphe + mémoire chaude Redis (TTL, baux, coordination multi-agents) |
grimoire doctor¶
Diagnostique la santé du projet (8 vérifications).
| Option | Description |
|---|---|
--fix |
Auto-correction des répertoires manquants |
Vérifie : config YAML, répertoires, archétype, backend, validation sémantique, dépendances optionnelles, version Python.
Avec --fix, les répertoires manquants sont créés automatiquement.
grimoire status¶
Affiche le statut du projet (agents, mémoire, config).
grimoire validate¶
Valide project-context.yaml contre le schéma Grimoire.
grimoire lint¶
Lint avancé : valide structure, types, contraintes et références dans le YAML config.
| Option | Description | Défaut |
|---|---|---|
--format, -f |
Format de sortie : text ou json |
text |
Accepte un chemin vers un fichier .yaml/.yml ou un répertoire (cherche project-context.yaml).
# Lint du projet courant
grimoire lint .
# Lint d'un fichier spécifique
grimoire lint configs/project-context.yaml
# Sortie JSON (pour CI)
grimoire lint . --format json
grimoire up¶
Amène le projet à la version du kit installé — c'est la commande de mise à jour.
Sur un projet neuf, elle initialise. Sur un projet existant, elle régénère les
artefacts appartenant au kit (_grimoire/kit/, wrappers d'agents, prompts,
instructions) et rafraîchit les artefacts du standard que le projet n'a pas
modifiés. Ce que le projet possède — project-context.yaml, .mcp.json, la
mémoire, les décisions de conformité, tout _grimoire/overrides/ — n'est jamais
réécrit.
Le profil du standard suit la même règle : les --needs passés à l'installation
sont persistés dans _grimoire/standard/install-manifest.yaml et réutilisés à
chaque up sans argument — un up nu ne rétrograde jamais un profil vers
starter (#344). Si le profil déjà en place est plus large que celui qu'un
up nu résoudrait, il est préservé et l'étape rapporte skipped. Seul un
--needs explicite qui réduit le périmètre est honoré, et il est alors
rapporté comme un changement de profil, jamais comme done.
L'écriture est différentielle : sans nouvelle version du kit, aucun fichier
n'est touché et le rapport indique kit artifacts already up to date. La
commande est donc sûre à lancer à tout moment.
grimoire migrate¶
Fait passer un projet créé avant la frontière kit/overrides sur cette frontière.
Opération unique : une fois faite, grimoire up suffit.
grimoire migrate [PATH] # montre ce qui bougerait, n'écrit rien
grimoire migrate [PATH] --apply # exécute, après snapshot
grimoire migrate [PATH] --adopt-kit # reprend la version du kit sur les fichiers qui la masquaient
grimoire migrate [PATH] --restore 20260826T193210Z
Chaque fichier de l'ancien emplacement est classé par son contenu : s'il
correspond à quelque chose que le kit a livré un jour (catalogue d'empreintes
embarqué), il est régénéré dans _grimoire/kit/ ; sinon il est considéré comme
étant celui du projet et déplacé dans _grimoire/overrides/. Un contenu non
reconnu n'est jamais supprimé.
Le plan signale les fichiers qui vont masquer un fichier du kit : ceux-là
cesseront de recevoir les mises à jour. S'ils ne contiennent aucune
customisation, --adopt-kit les remet sous la responsabilité du kit.
grimoire diff¶
Affiche les différences entre la config actuelle et les défauts de l'archétype.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire env¶
Affiche les informations d'environnement (version, Python, dépendances, OS).
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire version¶
Affiche des informations étendues sur la version (grimoire, Python, plateforme, projet actif).
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire schema¶
Exporte le JSON Schema (Draft 2020-12) pour project-context.yaml.
Utile pour l'autocomplétion YAML dans les IDE (VS Code, JetBrains) et la validation CI.
grimoire check¶
Exécute lint + validate + vérification de structure en une seule passe.
Phases :
- Lint — validation du schéma YAML
- Validate — vérification de la config chargée (
GrimoireConfig.validate()) - Structure — vérification des répertoires requis (
_grimoire/,_grimoire/_memory/,_grimoire-output/)
Code de sortie 1 si un problème est détecté.
Surfaces hôtes¶
Le groupe grimoire host projette le projet sur ce que chaque hôte sait
exécuter. Détail et dégradations par hôte : Surfaces hôtes.
| Commande | Description |
|---|---|
grimoire host list |
Hôtes connus, surfaces natives de chacun, hôte détecté |
grimoire host surface |
Description host-neutre du projet |
grimoire host sync --host all |
Générer les surfaces (--dry-run, --force) |
grimoire host status |
Écart entre ce que le projet déclare et ce que l'hôte exécute |
grimoire host run <slug> |
Corps d'une commande, pour un hôte sans commandes natives |
grimoire host hook --host <h> --event <e> |
Point d'entrée des hooks générés (stdin vers stdout) |
grimoire init, grimoire up --fix et grimoire standard init synchronisent
automatiquement ; l'appel manuel sert après l'ajout ou la modification d'une
persona.
host list remonte aussi ce qu'un hôte ne sait pas exécuter, avec le substitut
retenu — dont l'ouverture d'une session dans un agent, qu'aucun hôte ne sait
faire : la persona d'entrée est alors remise à la boucle principale par le hook
session_start. Voir Persona d'entrée.
Fournisseurs LLM¶
Le groupe grimoire providers croise le registre déclaratif
(llm-provider-registry.yaml, voir Compatibilité multi-provider)
et l'état de refroidissement/audit runtime pour répondre à : quel fournisseur
appeler maintenant, pour quel palier de coût (cheap/mid/strong) ?
| Commande | Description |
|---|---|
grimoire providers status [--json] |
Fournisseurs activés, modèles par palier, disponibilité (refroidissement + dernier audit), prochain choix |
grimoire providers audit [--json] |
Sonder chaque fournisseur activé sans dépenser (PATH, --version, modèles Ollama) et journaliser available/models_seen/probe_note dans l'état |
grimoire providers cooldown <id> --reason rate_limit\|timeout\|overloaded |
Enregistrer un échec à la main (429, timeout, 529) |
grimoire providers probe [<id>] [--json] |
Sonder (comme audit) puis rouvrir les fournisseurs fermés par une date de forfait illisible (unknown) ; une suspension à date n'est jamais levée |
grimoire providers quota [--json] |
Fenêtre de forfait lue dans les flux d'appel : lower_bound (minorant daté) ou unknown, jamais 0 |
grimoire providers history [--ledger-root <chemin>] [--json] |
Historique des dispatchs par couple (type de tâche, classe) et palier de départ recommandé |
providers audit ne fait jamais l'appel réel : présence du premier mot de
invocation sur le PATH, --version pour un exécutable reconnu (claude,
gemini, copilot, codex, ollama), et pour un fournisseur local (invocation
ollama ... ou provider_type: local) la liste des modèles via
GET /api/tags (hôte surchargeable par OLLAMA_HOST, timeout 3 s). Un
fournisseur jugé available: false est écarté par choose/candidates
jusqu'au prochain audit qui le retrouve — l'audit n'active ni ne désactive
jamais un fournisseur, enabled reste une décision de gouvernance.
providers history (issue #312) lit les événements task.dispatched du
Mission Ledger et compte, par couple (type de tâche, classe de
vérifiabilité) : le nombre de dispatchs et le taux d'escalade depuis
cheap et depuis mid (part des dispatchs où le palier de départ n'a pas
suffi). Pas de classifieur, pas d'entraînement — des compteurs. Avec au
moins 5 observations pour un couple, un taux d'escalade dépassant 40 %
depuis cheap fait recommander mid, dépassant 40 % depuis mid fait
recommander strong ; un couple monté à mid dont les 5 dernières
observations à ce palier n'ont plus escaladé, et qui n'a pas retenté
cheap depuis autant d'observations, voit cheap recommandé à nouveau
(re-sondage) — jamais sous le plancher qu'impose la classe (mid reste le
plancher d'une tâche V1). La colonne « départ recommandé » est exactement
ce que grimoire task dispatch retient par défaut pour ce couple.
Comptabilité du dispatch : coût par tâche résolue et pass^k¶
grimoire dispatch stats est la sœur de providers history : même idée
(compter, ne pas classifier), autre source et un autre angle. providers
history lit le Mission Ledger au grain de la tentative et compte des
taux d'escalade par couple (type de tâche, classe) ; dispatch stats lit le
journal de traces au grain de la cascade entière (un événement
dispatch.outcome par grimoire task dispatch ou par node de
grimoire flow run --executor dispatch réellement exécuté — jamais pour un
refus avant tout appel ni un --dry-run) et répond à deux questions que
seules des campagnes d'évals manuelles répondaient jusque-là (issue #442,
point 5 de l'audit de positionnement du 2026-09-12) : combien coûte une
tâche résolue, et à quel point une même tâche rejouée plusieurs fois
réussit-elle systématiquement ?
| Commande | Description |
|---|---|
grimoire dispatch stats [--since 30d] [--json] |
Coût par tâche résolue, taux d'escalade, part d'inexécutable — pour l'ensemble, par classe de vérifiabilité, par fournisseur et par flow — et pass^k sur les nœuds rejoués |
Coût par tâche résolue : le coût total de toutes les tentatives (vertes
et rouges confondues, un check rouge a quand même coûté un appel) divisé
par le nombre de dispatchs résolus — jamais divisé par le nombre total de
tentatives, qui sous-estimerait le coût réel d'un succès quand la cascade a
dû escalader. None sans aucun dispatch résolu, jamais une division par
zéro qui se lirait à tort comme un coût nul.
pass^k : quand un même nœud (le node d'un blueprint de flow, identifié par blueprint + id de node — ou, hors flow, directement l'identifiant de la tâche) a été dispatché au moins deux fois, cette répétition forme une « série ». Une série compte comme entièrement verte seulement si toutes ses exécutions ont résolu la tâche — la fiabilité au sens strict (k exécutions, toutes réussies), pas une moyenne de taux de réussite individuels. Le taux affiché est la part de séries entièrement vertes parmi celles observées au moins deux fois ; une tâche jamais rejouée n'entre dans aucun dénominateur.
--since 30d (ou 12h) ne garde que les dispatchs dont l'horodatage est
plus récent que cette ancienneté. Sans journal de traces sous
_grimoire-output/traces/, la commande n'échoue jamais : elle affiche qu'il
n'y a rien à montrer ({"overall": null} en JSON).
Le contrôle du standard dispatch.cost_slo (voir
Contrôles gouvernés) lit exactement les
mêmes agrégats — cette commande en est la vue humaine, jamais un second
calcul.
Routeur de LLM : une politique déclarative, tracée avant d'être activée¶
grimoire task dispatch choisit un palier de départ par la classe de
vérifiabilité et l'historique d'escalade, puis prend le premier modèle du palier
que le forfait n'a pas fermé. Le routeur (épopée #705, lot K9, issue #774) y
ajoute une décision déclarative et rejouable, sans rien changer à ce chemin
tant qu'on ne l'active pas : route(task, history, provider_state) choisit un
modèle d'après la tâche seule (classe, type, difficulté), l'historique de
réussite par modèle et la disponibilité du fournisseur. Il ne lit jamais le
quota, le budget ni les tokens restants, et ne change jamais de modèle pour
économiser : ces notions relèvent de l'admission, pas du choix. Un fournisseur
suspendu par son forfait y figure comme indisponible, jusqu'à sa date de
réouverture, comme un fournisseur injoignable.
| Commande | Description |
|---|---|
grimoire route explain <tâche> [--json] |
Rejoue la dernière décision task.routed à partir de ses entrées et de inputs_digest ; sortie 1 si le rejeu diffère, 2 sans décision |
grimoire route report [--json] |
Réussite au premier essai (pass^1) par (type, classe, modèle), escalade par couple, accord entre le routeur et le dispatch en mode shadow seulement (une issue session, defer ou refuse suivie d'un appel compte comme un désaccord) ; « non mesuré » sous 5 observations |
grimoire route eval --set <jeu> [--json] |
Seuil d'activation D16 hors ligne ; sortie 0 (tenu), 1 (non tenu), 3 (non mesuré) |
Politique : _grimoire/standard/routing-policy.yaml, sinon le défaut livré
par le kit. Toutes les règles qui correspondent s'appliquent et le palier retenu
est le maximum de leurs min_tier : le résultat ne dépend pas de l'ordre des
règles. route: session est absorbant, V2 n'a jamais de route autonome, aucune
règle qui correspond donne session, et le palier ne descend jamais sous le
plancher de la classe (V0 cheap, V1 mid). Les conditions admises sont
class, type, risk_any, exclusive_files_gt, needs_local : une règle qui
nomme un quota ou un budget invalide la politique. type et risk_any se comparent
en minuscules, sans espaces autour (comme les étiquettes de la tâche) : risk_any: [Security]
vaut [security], une étiquette vide est refusée. Une politique malformée, sans
version ou de version inconnue n'est jamais remplacée par le défaut : aucune
route autonome (on_invalid: refuse) : la décision tracée est refuse et
task dispatch ne lance aucune cascade (refus routing_policy_invalid, sortie 2),
en shadow comme en active. Seul un routeur en panne (exception) laisse le
dispatch suivre l'ancien chemin, avec une décision refuse et son erreur tracées.
version: 1
mode: shadow # défaut ; `active` fait gouverner la décision
rules:
- {id: r-risk, when: {risk_any: [security, migration]}, min_tier: strong}
- {id: r-v1, when: {class: V1}, min_tier: mid}
Tentatives : max_attempts (défaut 3) borne le nombre d'appels de la cascade
en mode active (appels en échec compris, tous paliers confondus) ; en shadow
rien n'est appliqué, la valeur n'est que tracée dans les entrées de task.routed.
Mode : shadow (défaut) émet task.routed avant chaque cascade et laisse le
dispatch suivre l'ancien chemin ; active fait gouverner la décision (palier de
départ sauf --start-tier explicite, ordre des fournisseurs, modèle dans le
palier). Dans le palier, le départage est : réussite au premier essai (au moins 5
observations, fenêtre de 50), puis, à réussite égale seulement, prix catalogue
croissant (un prix inconnu passe après), puis ordre déclaré. Les modèles
suspendus ou refroidis sont listés dans excluded[] avec leur raison. Sans
candidat, la décision est defer : jamais de descente de palier. Revenir à
shadow se fait en un seul champ.
En active, la décision n'est pas contournée : une issue session (règle
route: session, V2, aucune règle qui correspond) ou defer ne lance aucune
cascade (refus routed_to_session ou routed_defer, sortie 2, aucun
task.dispatched). Les fournisseurs appelés sont ceux que la décision admet : une
règle providers: {currency: local} vaut pour tous les paliers de la cascade, un
fournisseur d'une autre monnaie n'est jamais appelé, et au palier retenu seuls les
fournisseurs du classement le sont. En shadow, ces issues ne restent qu'une trace.
Attribution : chaque tentative (task.dispatched) compte pour le couple
(type, classe, modèle) de cette tentative ; un 429, un timeout ou une panne
d'appel sont non attribués et ne comptent jamais comme un succès.
Évaluation : le jeu est un fichier version: 1 / tasks: de tâches V0/V1
closes, chacune avec ses résultats enregistrés par modèle
(results: {<modèle>: {passed, cost_usd}}). Le routeur est comparé à la base
« fixe » (V0 vers cheap, V1 vers mid) : pass^1 du routeur >= base - 1 tâche
et coût connu <= celui de la base. Un coût inconnu, un résultat manquant ou
moins de 20 tâches rendent « non mesuré » : on n'active pas.
Besoins d'exécution : un flow déclare, le projet résout¶
Un node de flow ne référence pas pytest ni npm test en dur : son
acceptance peut déclarer un besoin ({"run_need": "test-runner"}) plutôt
qu'une commande (issue #205). grimoire flow run/resume résolvent ce
besoin à la commande réelle du projet au chargement du blueprint — en deux
temps, jamais un troisième : une déclaration explicite
(needs.commands dans project-context.yaml) l'emporte toujours sur la
détection par marqueur de projet (pyproject.toml, package.json,
Cargo.toml, go.mod). Un besoin qui ne se résout ni par l'un ni par
l'autre refuse le chargement du blueprint en le nommant, avant que le
premier node soit présenté à l'hôte — jamais une installation qui
échouerait au troisième node.
| Commande | Description |
|---|---|
grimoire needs resolve [--project-root .] [--json] |
Le verdict de résolution de chaque besoin du catalogue pour ce projet, et sa source (declared, detected, unresolved) |
Rétrocompatible : un blueprint à commandes en dur ({"run": "pytest -q"})
reste valide sans aucun changement. grimoire flow run affiche un
avertissement (jamais un refus) quand une commande en dur correspond mot
pour mot à un besoin résolu pour ce projet — une invitation à migrer vers
run_need, pas une obligation.
Web¶
Le groupe grimoire web est le chemin par lequel un agent atteint le web. Il
existe parce que le chemin nu ne suffit pas : web-browser.py rend son flux tel
quel, et un agent qui colle ce flux dans son contexte ne distingue plus ce qu'il
a lu de ce qu'on lui a demandé (OWASP LLM01).
| Commande | Description |
|---|---|
grimoire web fetch <url> [--selector CSS] [--timeout N] [--json] |
Récupérer une page et la rendre enveloppée « donnée externe, pas instruction » |
La sortie est encadrée par deux marqueurs portant un identifiant tiré au hasard
à chaque appel, que la page ne peut pas connaître ; une source qui tente de
recopier le marqueur le voit neutralisé et signalé. En --json, le résultat
porte origin: external : il ne peut pas relayer une approbation.
Le navigateur tourne en sous-processus — le script est en zone gelée et n'est jamais importé. Voir Contenu externe : donnée, pas instruction.
Standard agentique gouverné¶
Le groupe grimoire standard pilote le standard agentique (profils, patterns gouvernés, preuves). Référence des patterns : Contrôles gouvernés.
| Commande | Description |
|---|---|
grimoire standard profiles |
Lister les profils (starter → production) |
grimoire standard needs |
Lister les besoins projet (groupés par tier) |
grimoire standard plan --needs <id> |
Prévisualiser le plan (profil + patterns + extras) sans rien écrire |
grimoire standard init [.] --needs <id> |
Générer les artefacts standard du projet |
grimoire standard verify |
Vérifier les artefacts (fail-closed) |
grimoire standard audit |
Rapport de conformité + gaps restants |
grimoire standard score |
Calculer et persister un score de conformité |
grimoire standard gate check [--strict] [--no-run] |
Gate CI : échoue si une preuve obligatoire manque ; chaque manque nomme son chemin et un remède copiable. --strict exécute lui-même gate run-tests si la tâche doit une preuve d'exécution et qu'aucun run vert et frais n'existe ; --no-run restaure l'ancien comportement |
grimoire standard gate run-tests |
Exécuter la commande de test connue et enregistrer le verdict (test-run.json) |
grimoire standard task scaffold [--task-id X] [--dry-run] |
Créer, s'ils manquent seulement, les artefacts par tâche que les gates exigent (enveloppe, pack de preuve, registre d'affirmations, dossier d'acceptance, context bundle, decision trace), pré-remplis depuis le Mission Ledger ; idempotent ; le hook SessionStart le fait déjà pour la tâche active |
grimoire standard fix [--apply] |
Planifier / appliquer des correctifs sûrs |
grimoire standard doctor |
Vérifier la disponibilité des extras technologiques |
grimoire standard pattern |
Lister / inspecter les patterns |
grimoire standard detect-providers |
Détecter les providers LLM disponibles |
grimoire standard traceability [projet] |
Matrice exigences / contrôles / preuves de la norme ; avec un projet, le verdict de verify par artefact |
grimoire standard upstream |
Le standard amont a-t-il avancé depuis la révision épinglée (sortie 0/2/3) |
Sous-groupes (chacun avec --help) : board, memory, context, decision, rules, hooks, gate, events, pattern, knowledge, task.
Tâches agentiques¶
Le task board gouverné est une projection du Mission Ledger, pas une source
(voir ADR-005). Éditer
_grimoire/standard/task-board.yaml à la main ne change rien au ledger, et le
prochain export l'écrase.
| Commande | Description |
|---|---|
grimoire task board export [.] |
Régénérer le board depuis le Mission Ledger |
grimoire task board export . --dry-run |
Afficher la projection sans écrire |
grimoire task board export . --mission <id> |
N'exporter qu'une mission |
grimoire task board export . -o <chemin> |
Écrire ailleurs que dans le board du standard |
grimoire task add "<titre>" -a "<critère>" [--owner <qui>] [--ready] |
Ouvrir une tâche (un critère d'acceptation au moins) ; --ready la rend réclamable tout de suite, gate proposed_to_ready compris |
grimoire task list [--status <état>] [--mission <id>] |
Lister les tâches et leur colonne de board |
grimoire task show <id> |
Détailler une tâche et ce que chaque prochain pas exigera |
grimoire task claim <id> [--actor <qui>] [--host <où>] |
Réclamer une tâche prête (ready → claimed) |
grimoire task move <id> --to <état> |
Déplacer une tâche, si la machine à états et le gate le permettent |
grimoire task block <id> --reason "<motif>" |
Bloquer en disant pourquoi |
grimoire task close <id> |
Fermer une tâche vérifiée (verdict accepté exigé) |
grimoire task prioritize <id> --to low\|medium\|high\|critical [--reason "<motif>"] |
Changer la priorité (issue #638) — l'historique reste au ledger, le board se retrie |
grimoire task comment <id> "<texte>" [--kind comment\|directive] |
Poser un commentaire ou une consigne ; la session qui tient la tâche la lit au prochain UserPromptSubmit |
grimoire task cancel <id> --reason "<motif>" [--force] |
Annuler avec sa raison (obligatoire) ; tenue par une autre session, elle exige --force |
grimoire task ack <id> <dir-…> |
Accuser réception d'une consigne de l'orchestrateur |
grimoire task link <id> --depends-on <id> |
Déclarer une dépendance |
grimoire task context <id> |
Produire le context bundle d'une tâche réelle |
grimoire task trace <id> [--causes] |
Timeline unifiée d'une tâche : transitions, outils refusés, gates rouges, checkpoints, abort, preuves, incidents |
grimoire task trace-export <dest> [--format otel\|langfuse] [--mission-id <id>] |
Exporte le TraceLedger en JSONL, conventions sémantiques OTel GenAI ou contrat REST Langfuse |
grimoire task recall <id> |
Ce que la mémoire du projet sait de cette tâche et de ses voisines — borné en tokens |
grimoire task dispatch <id> --check "<commande>" [--check ...] [--dry-run] [--max-tier cheap\|mid\|strong] [--start-tier cheap\|mid\|strong] [--provider <id>] [--timeout <s>] |
Déléguer la tâche en cascade par palier de fournisseur |
Sans ledger, la commande d'export refuse et sort en erreur plutôt que d'écrire un board vide — écraser le travail déclaré par du néant serait pire que ne rien faire.
Chaque transition d'état (claim, move, block, close, cancel) franchit deux
portes avant de toucher le ledger : la machine à états, puis le gate de preuve de
_grimoire/standard/evidence-gates.yaml. Un refus nomme la preuve manquante et le
remède ; rien n'est écrit. Après une écriture acceptée, le board du standard est
reprojeté depuis le ledger si le projet est enrôlé (_grimoire/standard/ présent)
— plus besoin de relancer task board export pour qu'un claim se voie.
Les mêmes gestes sont exposés aux agents par le serveur MCP (task_add,
task_list_ready, task_show, task_claim, task_update, task_context) :
même service (TaskService.add pour l'ouverture), même gate, même refus. Voir
Intégration MCP.
Vérifiabilité d'une tâche¶
grimoire task show <id> et la projection du board (verifiability) portent
une classe dérivée — jamais déclarée — depuis le texte des critères
d'acceptation et des preuves attendues : V0 si tous nomment un verdict
qu'un programme rend seul (test, lint, schéma, gate, code de sortie, build/CI,
fichier attendu), V1 si au moins un critère nomme une revue ou une
validation par une personne ou un agent sans qu'aucun autre ne reste ambigu,
V2 sinon — y compris une tâche sans aucun critère. Un critère formulé de
façon vague (« le code est propre ») ne peut jamais produire un V0 : un seul
critère ambigu suffit à faire monter la classe, jamais à la faire descendre.
task show affiche, critère par critère, le motif reconnu — c'est ce qui rend
lisible pourquoi une tâche n'est pas au niveau qu'on lui prêtait.
Plafonds MAST par instance de workflow¶
Chaque instance créée par le RuntimeKernel (create_instance) porte deux
plafonds indépendants, surchargeables à la création (max_tool_calls=50,
max_budget=100 par défaut) : le nombre d'appels d'outils que
mediate_tool médiera — la seule unité de « tour » que le kernel observe —
et un budget d'unités de coût consommées par ces mêmes appels (1 unité par
appel par défaut ; un appelant qui connaît un coût réel, en tokens ou en
devise, peut passer cost= à chaque appel). Le kernel ne voit aujourd'hui
passer ni tokens ni coût ailleurs, d'où ce choix par défaut. Au premier appel
qui dépasserait l'un des deux plafonds, l'instance passe dans l'état terminal
refused : un checkpoint est écrit, un événement workflow.refused est
journalisé, et l'appel — comme tout appel suivant sur cette instance — rend
False sans jamais lever d'exception ni laisser l'instance continuer en
silence. Voir src/grimoire/runtime/kernel.py et schemas.py
(WorkflowStatus.REFUSED, RunEventType.WORKFLOW_REFUSED).
Pourquoi une tâche s'est arrêtée¶
grimoire task trace <id> lit les journaux qui portent chacun le task_id
— le Mission Ledger (transitions, incidents), le TraceLedger des hooks (outils
autorisés ou refusés par la policy, clôtures refusées, gates de
transition rouges, dispatch d'agent ou non-choix), le RuntimeKernel (run
events, checkpoints, abort/refus et leur raison), l'EvidenceService
(packs, verdicts) et, s'il existe, l'export OTel du TraceLedger (grimoire
task trace-export --format otel, #322) — et les trie dans le temps. Cette
dernière source lit un fichier déjà écrit par trace-export (emplacement
conventionnel : <traces>/otel-export.jsonl) ; elle ne relance jamais l'export
elle-même. Les entrées qui expliquent un arrêt sont marquées et reprises dans
une section « Cause(s) d'arrêt » ; --causes n'affiche qu'elles ; --output
json rend la timeline complète avec ses sources. Une source absente est
nommée comme telle ; rien n'est créé, rien n'est inventé. bootstrap se trace
aussi — c'est là que les hooks écrivent tant qu'aucune tâche n'est réclamée.
Le cockpit et l'atelier affichent la même timeline dans l'espace Exécuter
de la vue de travail (onglet Timeline, drill-down depuis une carte du board),
et l'espace Observer y renvoie depuis un span OTel qui porte un
grimoire.task_id — voir la page du cockpit, section
« Le board (espace Exécuter) ».
GAO-livrer-la-ti-001 — Livrer la timeline (running)
21:14:39 ledger ready → claimed par claude (claim claude@claude-code)
✗ 21:14:40 hooks Bash refusé par la policy (args 3f2a9c1e0b7d4e11)
✗ 21:14:41 gate gate « in_progress_to_review » refuse la transition — manque : evidence_pack, decision_trace
✗ 21:14:42 runtime workflow WFI-recipe-livraison-001 abandonné — raison : suite pytest rouge
Cause(s) d'arrêt : 3
Dispatch par cascade¶
grimoire task dispatch <id> délègue une tâche à un fournisseur LLM du
registre (llm-provider-registry.yaml), en cascadant par palier de coût
(cheap → mid → strong) selon la classe de vérifiabilité de la tâche : une
tâche V2 est refusée avant tout appel (aucun verdict mécanique ne peut la
juger), une V0 cascade depuis cheap, une V1 cascade depuis mid et,
au vert, passe en needs_verification au lieu d'être considérée close — le
check mécanique n'y est qu'un indice, la classe exige encore un regard
humain. Au moins un --check <commande> est obligatoire (code de sortie 0 =
vert, toutes doivent l'être) ; sans lui, la classe dit que le verdict est
mécanique, encore faut-il dire lequel.
Un échec d'appel (429, timeout, code de sortie non nul) passe au fournisseur
suivant du même palier et pose un refroidissement (grimoire providers
status) ; un --check rouge passe au palier suivant. Chaque tentative laisse
un événement task.dispatched au Mission Ledger (palier, fournisseur,
modèle, durée, verdict, coût si la sortie est un JSON portant
total_cost_usd, type de tâche, classe de vérifiabilité, palier de départ et
sa raison). --dry-run montre la classe, la chaîne de paliers prévue et le
prompt sans rien appeler ; --max-tier borne la cascade ; --provider la
restreint à un seul fournisseur.
Code de sortie : 0 si la chaîne finit au vert, 1 si elle s'épuise sans
verdict vert, 2 sur un refus (V2, aucun --check, aucun fournisseur
invocable). Ce lot ne worktree pas automatiquement : travaillez sur une
branche propre avant de dispatcher — le fournisseur délégué écrit dans le
dépôt courant.
Palier de départ ajusté par l'historique¶
Le palier de départ de la cascade n'est plus fixe : sauf --start-tier
explicite, il vient de l'historique des dispatchs passés pour le couple
(type de tâche, classe de vérifiabilité) — voir grimoire providers
history (issue #312). Par défaut, cheap pour V0 et
mid pour V1 (le plancher que la classe impose, jamais franchi vers le
bas) ; ajusté vers mid, puis strong, quand un couple escalade trop
souvent depuis son palier habituel, et re-sondé vers le bas quand il cesse
d'escalader et que le palier inférieur n'a pas été retenté depuis un
moment. Le rapport (start_tier, start_tier_reason) et l'événement
task.dispatched disent tous deux quel palier a été retenu et pourquoi ;
--start-tier cheap|mid|strong l'impose sans consulter l'historique.
Le pilote : combien dépenser par node (issue #209)¶
Une fonction de décision — jamais une couche — appelée avant chaque node
dispatché par flow run --executor dispatch : le graphe dit quoi, le
pilote dit combien. Une politique de projet optionnelle,
_grimoire/standard/pilot.yaml, la paramètre ; absente, le comportement est
exactement celui décrit ci-dessus (palier de départ ajusté par
l'historique, aucun plafond).
start_tier:
V0: mid # ne peut jamais descendre sous le plancher de la classe
max_escalations: 1 # 0 = aucune escalade permise, absent = pas de plafond posé ici
max_cost_usd_per_node: 0.50
on_unknown_cost: stop # défaut ; ou continue_flagged
max_cost_usd_per_node s'applique dans missions.dispatch.run_dispatch
lui-même (max_cost_usd) : entre deux paliers, jamais au milieu d'une
tentative ni après un vert déjà acquis — seule l'escalade vers un palier
plus cher est abandonnée. Le rapport porte alors cost_capped (un message
nommé) plutôt qu'une chaîne simplement épuisée ; côté flow status, le node
apparaît avec le verdict cost_capped. Un pilot.yaml malformé refuse
nommément le chargement plutôt que de retomber en silence sur « aucun
plafond » — contrairement à orchestration-policy.yaml, un plafond de coût
est un mécanisme de sécurité.
Un fournisseur qui ne rend pas son coût (aucun JSON portant total_cost_usd,
le cas de la plupart des fournisseurs headless) laisse ce coût inconnu :
il n'est jamais compté pour zéro. on_unknown_cost: stop (défaut,
fail-closed) arrête l'escalade dès qu'un palier a répondu sans coût alors
qu'un plafond est posé — le rapport porte cost_capped avec la raison
cost_unknown (cost_cap_reason). continue_flagged laisse escalader ;
le coût reste alors signalé lower_bound (>= 0.4200 USD (1 non pricés)) ou
unknown dans le rapport, la trace dispatch.outcome, grimoire dispatch
stats, flow status, flow list et le contrôle dispatch.cost_slo
(tous rendent le même format, avec le décompte des appels sans prix). Dans un
flow, cost_unknown ne sert qu'à l'escalade, à l'enchaînement des nodes d'un
sous-flow et aux passes optionnelles de budget (non lancées sous stop,
skipped_reason: cost_unknown) : un coût inconnu ne jette jamais un node déjà vert ni les éléments
frères d'un fanout, verify-panel, loop-until-dry, judge ou replay-diff
(seul un montant connu qui atteint le plafond, cost_reached, les arrête).
Ces nodes continuent donc sous stop malgré un coût inconnu, mais ne passent pas pour
« sous le plafond » : le node porte cost_cap_unevaluated: true (plafond posé, politique
stop, appels sans prix — le plafond n'a pas pu être jugé), à lire avec cost_status.
Le node porte cost_cap_reason (cost_reached | cost_unknown). La politique
assume_tier_ceiling (estimer au plafond du palier) n'existe pas encore.
Classe de relisibilité¶
Un dispatch qui finit au vert classe aussi le diff qu'il a produit
(git diff --name-only dans le projet) : review_required s'il touche une
surface sensible, review_optional sinon. Surfaces par défaut, génériques : exports publics (*/__init__.py), surfaces d'entrée (*/cli/*, */mcp/*, */api/*), schémas (*schema*), standard du projet (_grimoire/standard/*, framework/agentic-standard/*), vocabulaire de décision (*/verifiability.py), politiques, sécurité et hooks (*/policies/*, */security/*, */hooks/*). Un diff confiné à tests/ ou
docs/ reste toujours review_optional. La liste se surcharge projet par
projet dans _grimoire/standard/orchestration-policy.yaml (clé
review_surfaces, une liste de globs). Un projet qui n'est pas un dépôt git
ne permet pas de calculer le diff : la classe reste review_optional, avec
une note qui le dit plutôt qu'un silence trompeur. Le rapport (review,
review_files) et l'événement task.dispatched portent tous deux le
résultat ; task show affiche celui du dernier dispatch.
Incertitudes déclarées¶
Le prompt envoyé à l'ouvrier délégué se termine par une consigne : rendre un
bloc délimité ```grimoire-uncertainties contenant une liste JSON
d'objets {"where": ..., "what": ..., "why": ...} — le canal d'escalade le
moins cher qui existe, lu ici mécaniquement plutôt qu'en prose. Le dispatch
l'extrait de la sortie de l'ouvrier (le texte brut, ou le champ result si la
sortie est un JSON qui l'enveloppe) et stocke le résultat sous uncertainties
dans le rapport et dans l'événement task.dispatched. Un bloc absent est une
liste vide, silencieusement — la plupart des ouvriers n'y répondront pas
encore ; un bloc présent mais illisible (JSON invalide, pas une liste) est
aussi une liste vide, mais avec un avertissement dans uncertainty_warnings ;
un objet du bloc sans les trois clés est ignoré avec son propre avertissement,
les autres objets du même bloc restent gardés. Rien de tout cela ne change le
verdict ni le code de sortie du dispatch. task show affiche les incertitudes
du dernier dispatch.
Ce que le claim rappelle¶
grimoire task recall <id> (#141) assemble ce qu'une tâche et ses voisines ont
déjà traversé : son propre historique (tentatives précédentes bloquées ou
échouées), ses tâches voisines — liées par task link, de la même mission, ou
au titre proche — avec la cause de leur arrêt même si elles ont depuis été
rouvertes, et ce que la mémoire du projet a consolidé sur des sujets voisins
quand un backend mémoire est configuré (project-context.yaml). Sans lui, le
rappel reste utile depuis le seul Mission Ledger. Le texte rendu est borné en
tokens : c'est un rappel, pas un rapport.
[Grimoire — rappel de tâche] GAO-migrer-le-se-002 :
Tâches voisines :
- GAO-migrer-le-se-001 (même mission, failed)
cause : connexion refusée par la base cible : pool épuisé
Le même rappel est injecté par le hook SessionStart, entre la persona
d'entrée et la directive du standard, seulement pour une tâche réclamée
(task.claim posé — une tâche proposed ou ready ne rappelle rien) ; et par
l'outil MCP task_recall, qui résout la tâche active de la même manière que
task_context quand aucun identifiant n'est donné. À la clôture ou au
blocage d'une tâche, TaskService consolide ce qui a été appris dans la
mémoire du projet (decisions à la clôture, failures au blocage) — jamais
sur un mouvement ordinaire.
Quelle tâche la session porte¶
Les hooks (SessionStart, UserPromptSubmit, Stop) et grimoire standard
activation-context résolvent la tâche courante dans cet ordre :
GRIMOIRE_TASK_ID— un opérateur dit de quelle tâche la session parle ;- le claim actif du Mission Ledger : l'unique tâche
claimedourunning, restreinte aux claims deGRIMOIRE_ACTORquand cette variable est posée ; - l'unique carte
in_progressdu board (projet sans ledger) ; bootstrap.
Deux claims simultanés (ou deux cartes in_progress) sont ambigus : le niveau
est sauté plutôt que deviné, et GRIMOIRE_TASK_ID tranche. task_context sans
argument, côté MCP, rend la tâche résolue et la règle qui l'a choisie.
Neuf états côté ledger se projettent sur les huit colonnes du standard. Les
fusions sont décidées et testées : claimed et running deviennent
in_progress, needs_verification devient review, failed devient blocked
(avec un motif), closed devient accepted, cancelled devient archived.
Mémoire¶
Le groupe grimoire memory pilote le sous-système mémoire. Concepts, backends
et projections : Système de mémoire.
| Commande | Description |
|---|---|
grimoire memory status |
Santé du backend, nombre d'entrées, configuration |
grimoire memory up |
Mettre en place la stack mémoire complète, plan par plan |
grimoire memory remember <texte> |
Écriture typée idempotente — même texte et même agent n'écrivent qu'une fois |
grimoire memory recall <requête> |
Rechercher parmi les mémoires typées |
grimoire memory search <requête> |
Recherche par mot-clé ou similarité sémantique — fusionne vectoriel et BM25 (RRF) dès que le projet possède les deux ; --no-hybrid force le backend seul |
grimoire memory list |
Lister les mémoires stockées, paginées |
grimoire memory delete <id> |
Supprimer une entrée |
grimoire memory gc |
Consolider et compacter |
grimoire memory export / import |
Exporter vers JSON, réimporter |
grimoire memory reindex-lexical |
Reconstruire l'index lexical compagnon |
grimoire memory gate |
Gate de parité Memory OS entre Weaviate et Neo4j |
grimoire memory graph / vector |
Synchroniser et vérifier les projections |
grimoire memory bundle |
Construire, installer et vérifier les bundles de modèles d'embedding |
grimoire memory shared |
Mémoire transverse : ce qui reste vrai d'un projet à l'autre |
grimoire memory facts / diary |
Graphe de faits temporels, journaux d'agents |
grimoire memory migrate |
Planifier et exporter les migrations Memory OS |
grimoire memory taxonomy |
Taxonomie aile / salle / pièce |
Hooks git¶
| Commande | Description |
|---|---|
grimoire hooks list |
Lister les hooks disponibles et leur état d'installation |
grimoire hooks status |
Résumer l'état d'installation — sortie 1 si incomplet |
grimoire hooks install |
Installer les hooks git Grimoire dans le dépôt |
Blueprints et flows¶
Un blueprint décrit un flow agentique comme un graphe de nodes typés. Ces commandes le manipulent sans passer par l'atelier web. Détail du format et de l'éditeur : Mode local et blueprints.
| Commande | Description |
|---|---|
grimoire blueprint new <id> |
Scaffolder un .blueprint.json valide depuis un modèle embarqué |
grimoire blueprint validate <fichier> |
Valider : JSON Schema, puis contrôles structurels de compilation |
grimoire blueprint compile <fichier> |
Compiler en mission pack, avec les mêmes règles fail-closed que l'atelier |
grimoire blueprint evals <fichier> --record <relevé> |
Rejouer les évals déclarées contre un relevé d'exécution |
Le rejeu ne fabrique aucun verdict : un cas absent du relevé est rapporté comme non exécuté, jamais comme échoué.
validate et compile ont deux couches de contrôle, dont la première demande
le paquet jsonschema. Quand il manque, la couche ne s'exécute pas et les deux
commandes refusent : un contrôle qui n'a pas eu lieu ne peut pas conclure à
un succès. --allow-skipped-schema accepte explicitement le contrôle partiel.
grimoire flow — le moteur conduit, l'hôte exécute un node¶
blueprint compile aplatit un blueprint en un unique prompt markdown : le
modèle improvise l'ordre. grimoire flow inverse cela (#204) : le
RuntimeKernel conduit un blueprint node par node, chaque node reçoit un
contrat borné (entrées, frontière d'outils, critères d'acceptation, contrat
de sortie), et l'hôte — jamais le kit — exécute le node. compile reste
un repli valide pour les hôtes sans exécuteur de node ; flow ajoute une
seconde sortie, il ne retire rien.
| Commande | Description |
|---|---|
grimoire flow run <fichier> |
Démarrer un run et présenter le contrat du premier node ; sans argument, liste les runs |
grimoire flow status <run-id> |
État du run : node courant, nodes faits, dernier refus, contrat courant |
grimoire flow resume <run-id> --result <fichier> |
Vérifier la sortie du node courant contre son contrat ; avance ou suspend |
grimoire flow abort <run-id> [--reason] |
Abandonner un run — terminal, jamais repris |
grimoire flow extract <run-id> [--out <fichier>] |
Extraire un blueprint brouillon de la séquence réellement exécutée par ce run |
grimoire flow list [--require-measure <blueprint-id>] |
Le registre local des flows : runs connus par blueprint, avec leur mesure de dispatch |
Un checkpoint par node : un run interrompu reprend exactement au node courant, jamais du début. Une sortie non conforme au contrat de sortie du node suspend le run en nommant le node et la pin fautifs, avec un code de sortie non nul — jamais un échec muet.
flow extract — un flow s'extrait d'un run, il ne se dessine pas (#210)¶
Créer un flow devient éditer quelque chose qui a déjà fonctionné plutôt que
partir d'un canevas vide. grimoire flow extract <run-id> joint les
métadonnées du run (ordre topologique, blueprint source) au Mission Ledger
(commande réellement exécutée par node, via --executor dispatch) pour
produire un blueprint brouillon dans le même format .blueprint.json — texte
d'abord, lisible et diffable, que le Studio peut ensuite éditer.
Par node, trois choses observées, jamais devinées : l'acceptance déclarée
d'un node complété par la cascade est remplacée par la commande
réellement exécutée ({"run": "..."}), réinférée en {"run_need": "..."}
quand elle correspond caractère pour caractère à un besoin résolu pour ce
projet (issue #205) ; un node jamais dispatché (classe V2, ou exécuté par
un hôte interactif sans passer par la cascade) garde son acceptance d'origine
verbatim ; un node jamais atteint (run incomplet ou abandonné) est marqué
not_reached, sans qu'aucune commande n'y soit inventée. Chaque node du
brouillon porte un objet "extraction" (status, et note sur un refus)
qui dit lequel de ces trois cas s'est produit.
Le brouillon extrait est rejouable : flow run/resume le chargent comme
n'importe quel blueprint, et reproduisent la même séquence de nodes que le
run source sur le même projet.
kind: "composite" — un flow est un node (lot 3, issue #206)¶
Le schéma réservait déjà kind: "composite" pour un sous-flow (ref =
use-case:<id> ou un chemin .blueprint.json), mais seul le compilateur
Studio le validait — le moteur de flows ne l'exécutait pas. Depuis cette
issue, un node composite expose des pins comme n'importe quel node, et son
exécution (sous --executor dispatch) lance la ref comme un run à part
entière : son propre run_id, ses propres checkpoints, son propre Mission
Ledger — lié au parent par FlowRunMeta.parent_run_id/parent_node_id.
ref reconnaît trois formes, jamais une quatrième inventée :
- un chemin se terminant par
.blueprint.json, résolu relativement au blueprint qui le référence puis à la racine du projet ; - un id de flow nu, résolu contre le registre local
(
registry/blueprints/<id>.blueprint.json) ; use-case:<id>— réservé à l'expansion Studio/catalogue : le moteur de flows refuse cette forme au chargement, il ne l'exécute pas.
Trois refus, tous au chargement du blueprint parent, jamais quand le node composite serait présenté à un exécuteur :
- référence introuvable (fichier absent, id absent du registre) ;
- cycle de composition — un blueprint qui se référence lui-même, directement ou via un intermédiaire ;
- profondeur de composition supérieure à 3 (un flow racine qui référence un sous-flow qui en référence un troisième est la limite).
Le coût du sous-flow est remonté au node composite : flow status et le
rapport de --executor dispatch montrent son cost_usd comme la somme des
coûts de tous les nodes de l'enfant. Le plafond du pilote (issue #209,
max_cost_usd_per_node) s'applique à ce total, vérifié entre chaque node
de l'enfant — jamais après un node déjà vert : un dépassement abandonne le
run enfant (flow status <child-run-id> le montre aborted) et ferme le
node composite en cost_capped, comme un node simple dont la cascade aurait
renoncé au palier suivant.
Sous l'exécuteur interactive (par défaut), un node composite n'est pas
auto-lancé — son contrat affiche composite:<ref> comme frontière d'outils,
et l'hôte lance lui-même grimoire flow run <ref> avant de soumettre un
résultat conforme aux pins déclarées, comme pour tout autre node interactif.
flow extract (#210) ne l'aplatit jamais : le node composite reste
kind: "composite" avec sa ref d'origine dans le brouillon, et son
extraction porte le child_run_id du sous-flow qu'il a lancé quand il y en
a un — le sous-flow s'extrait séparément, sur son propre run_id.
grimoire.flows.registry.describe_flow (utilisé par flow list, ci-dessous)
lit, en plus, version/kitMin/kitMax au niveau du blueprint (tous
optionnels — version retombe sur 0.0.0) et l'union des run_need
déclarés par le flow et par tous ses sous-flows composite.
Les sept genres de node (lot 4, issue #207)¶
composite (ci-dessus) est le cas dégénéré : un sous-flow, une tentative,
aucune agrégation. Sept genres de plus généralisent le même mécanisme —
lancer un ou plusieurs sous-flows enfants — avec chacun sa propre politique
d'agrégation. Aucun n'est exprimable dans un document de consignes statique ;
tous deviennent directs dès que le moteur tient l'état. Chacun n'existe que
sous --executor dispatch (grimoire.flows.genres, fonctions
_execute_<genre> — module compagnon de grimoire.flows.dispatch_executor,
extrait de lui pour rester sous le seuil du cliquet de lignes) ; sous
interactive, le contrat affiche le genre et sa
ref comme frontière d'outils, l'hôte orchestre lui-même.
Paramétrage refusé nommément au chargement du blueprint
(grimoire.flows.blueprint_loader._validate_genre_config) — jamais un
TypeError/KeyError anonyme à l'exécution :
| Genre | ref |
config.<genre> requis |
|---|---|---|
fanout |
sous-flow modèle | — (voir ci-dessous) |
verify-panel |
sous-flow vérificateur | k (entier ≥ 2), angles (liste de k chaînes) |
loop-until-dry |
sous-flow | maxRounds (entier ≥ 1) |
judge |
sous-flow candidat | n (entier ≥ 2), angles (liste de n chaînes) |
checkpoint |
ignorée (chaîne vide par convention) | — |
budget |
ignorée — voir config.budget.passes |
maxCostUsd (nombre > 0), passes (liste non vide de refs) |
replay-diff |
sous-flow | — |
fanout — un node produit N éléments, N sous-flows instanciés, les
résultats sont recollés. Deux temps : le node est d'abord dispatché
normalement (comme un node ordinaire), sa sortie doit porter, en plus de ses
pins déclarées, une clé fanout_items (liste non vide) ; le moteur instancie
alors un sous-flow (ref) par élément. N est borné par
pilot.max_fanout_n (_grimoire/standard/pilot.yaml) — absent, le
fan-out est refusé : jamais une politique manquante ne vaut un plafond
infini implicite. Vert seulement si les N enfants finissent tous verts ;
recoller un résultat partiel comme s'il était le tout serait l'invention que
l'issue refuse.
verify-panel — k vérificateurs indépendants (config.verifyPanel.k),
chacun sous un angle distinct (.angles, instruit de chercher à réfuter,
jamais de confirmer par défaut), majorité requise. Coût = k tentatives,
toujours — jamais une cascade qui s'arrête au premier consensus
apparent : un plafond de coût qui empêche de compléter les k tentatives
referme le node en cost_capped, jamais sur un vote partiel (« jamais un
vert sur 1/k »).
loop-until-dry — relance jusqu'à config.loopUntilDry.maxRounds tours
sans nouveauté. Chaque tour doit porter une clé novelty_key (chaîne) dans
sa sortie ; la déduplication porte contre tout le vu depuis le premier
tour (un ensemble cumulatif), jamais seulement contre le dernier tour
retenu. maxRounds est une borne dure, distincte d'un séchage réel
(loop_until_dry_stop_reason : "dry" / "max_rounds" / "cost_capped").
judge — N tentatives sous angles imposés (config.judge.n/.angles),
puis le node lui-même est dispatché une seconde fois comme juge (V1 —
« un humain choisit »), avec le résumé des N tentatives dans son contexte de
tâche ; sa sortie doit porter judge_winner (index 0..N-1). La trace des N
tentatives survit dans leurs propres runs (Mission Ledger de chaque enfant),
jamais seulement dans un champ éphémère du node.
checkpoint — approuver, refuser, amender. Toujours une décision
d'hôte forcée, jamais auto-décidée par la cascade (même sous
--executor dispatch, ce genre pend systématiquement, comme un node V2).
La reprise (flow resume --result, forme interactive, quel que soit
l'exécuteur qui a conduit le reste du run) doit porter
checkpoint_decision (approve/reject/amend) ; reject bloque le run
en nommant le motif (checkpoint_reason) dans l'événement de refus du
kernel — « le motif dans le graphe de décision » — une reprise ultérieure
rouvre exactement ce même node. amend (W2-10) demande une révision : le
node reste ouvert, la décision et son motif sont inscrits dans le journal du
run (relu par flow status) et comptés. accept_as_is n'est accepté qu'après
config.checkpoint.max_amendments amendements (entier >= 1, 3 par défaut) ; il
exige checkpoint_reason (le risque nommé), inscrit accepted_risk, et pose
task.risk_accepted sur la tâche du ledger liée au run (--task-id) si elle
existe ; le ledger le rejoue dans la tâche (accepted_risks) et classify la remonte
au moins en V1 pour toute surface (task show, MCP task_show/task_claim,
dispatch_advice, transition needs_verification de task dispatch).
Limite : le compteur est celui du journal du run, amend non attesté compris.
budget — plafond de coût déclaré (config.budget.maxCostUsd),
abandon des passes optionnelles avant dépassement. passes est une liste
de refs de sous-flows ; la première est obligatoire (son échec fait échouer
le node) ; chacune des suivantes n'est lancée que si le coût cumulé reste
sous le plafond — sinon abandonnée, jamais tentée, sans faire échouer le
node. Distinct de pilot.max_cost_usd_per_node : ce plafond-ci est déclaré
par le blueprint, propre à ce node.
replay-diff — rejoue le même flow (ref) sur la même entrée (deux
runs enfants, sans variation d'un à l'autre) et compare les traces.
replay_diverged (booléen, dans la sortie) dit si les deux traces
(statut + nodes complétés) divergent — une divergence est un signal,
jamais un défaut : le verdict reste vert tant que les deux relectures
finissent, qu'elles divergent ou non.
Coût et pilote, pour les sept genres : pilot.max_cost_usd_per_node
s'applique au total de chaque genre, jamais à une seule tentative —
vérifié avant chaque nouveau sous-flow lancé, jamais après un enfant déjà
vert (même garantie que pour composite). Extraction : flow extract
ne les aplatit jamais — kind, ref et config.<genre> survivent
verbatim dans le brouillon, exactement comme composite. Rust : aucun
changement — les sept genres sont de l'orchestration Python (E/S, lancement
de runs enfants), hors périmètre des fonctions pures déjà portées par
grimoire-flows-core ; la grille de transitions et les contrats de node
n'ont pas changé.
--executor dispatch — la cascade par classe de vérifiabilité (#311)¶
run et resume acceptent --executor dispatch (défaut : interactive,
inchangé). Au lieu d'attendre un --result de l'hôte, chaque node est confié
à grimoire.flows.dispatch_executor : une tâche de mission est créée (ou
retrouvée) au ledger, liée au run et au node, avec pour critères
d'acceptation ceux du node et pour preuve attendue son contrat de sortie ;
elle est dispatchée en cascade (run_dispatch, #323) — l'ouvrier écrit sa
sortie dans un fichier JSON que le kit vérifie contre les pins du node, avec
la même fonction que flow resume, et exécute l'acceptance structurée du
node quand le blueprint en déclare une (voir « Acceptance structurée d'un
node », ci-dessous, issue #428) : une enveloppe conforme ne suffit plus seule
à fermer un node V0 dont l'acceptance déclare une commande.
La chaîne suit la classe de vérifiabilité du node (#309) :
- V0 :
cheap→mid→strong. - V1 : démarre à
mid; un vert marque le node à relire (needs_verificationcôté ledger), jamais une fermeture. - V2 : refusé avant tout appel — le node revient à l'hôte, exactement
comme
flow run/flow resumeinteractifs : le contrat est présenté,flow resume --resultreprend la main.
run --executor dispatch enchaîne les nodes tant que la cascade reste
verte, checkpointe après chacun, et s'arrête au premier node rouge (chaîne
épuisée), acceptance inexécutable, ou V2, avec un rapport par node
(fournisseur, tentatives, verdict, coût, escalades, statut d'acceptance)
plutôt qu'un contrat. resume --executor dispatch (sans --result) reprend
de la même façon le node que le run avait laissé ouvert — utile après un
crash comme après une suspension V2 corrigée autrement. flow status
affiche, pour tout node dispatché, fournisseur, tentatives, verdict,
relecture requise, incertitudes déclarées et statut d'acceptance
(exécutée/inexécutable/jugée) — lus depuis l'événement
task.dispatched du Mission Ledger, valables même dans un process qui n'a
pas fait le dispatch. --max-tier et --timeout bornent la cascade comme
sur grimoire task dispatch.
Acceptance structurée d'un node (issue #428)¶
Un node V0 est « vérifiable mécaniquement » : par défaut, le vocabulaire de
son acceptance textuel (« la suite de tests passe », …) sert uniquement à
dériver sa classe de vérifiabilité (#309) — le gate de la cascade ne vérifie
que la conformité de l'enveloppe JSON au contrat de sortie du node, jamais le
texte lui-même. Sur un flow réel rejoué le 2026-09-11 (épic #307, lot 3),
cela a laissé fermer vert un node dont la vraie suite pytest ne pouvait pas
même être collectée (dépendance absente) : l'enveloppe était conforme, rien
d'autre n'avait tourné.
node.acceptance accepte désormais, en plus d'une chaîne libre
(rétrocompatible, comportement inchangé), une entrée structurée que le gate
exécute réellement après la réponse de l'ouvrier — dans le projet, en
sous-processus, délai borné :
{"run": "pytest -q tests/test_x.py", "expect_exit": 0, "cwd": ".", "timeout_s": 120, "expect_stdout_contains": "passed"}
Seul run est requis ; expect_exit (0 par défaut), cwd (. par défaut),
timeout_s (120 par défaut) et expect_stdout_contains (aucun par défaut)
sont optionnels. Deux formes d'evidence mécanique existent aussi, pour éviter
d'écrire une commande à la main :
{"path_exists": "dist/rapport.json"}— un fichier doit exister.{"test": "tests/test_x.py::test_y"}— un test nommé doit passer (traduit en une invocationpytestdu seul identifiant déclaré).
acceptance peut mélanger texte libre et entrées structurées dans la même
liste. Une forme structurée invalide (clé inconnue, plusieurs clés sur la
même entrée, type incorrect) est un refus nommé au chargement du
blueprint (GrimoireRuntimeError), jamais un gate qui échouerait ouvert
plus tard — et le kit n'infère jamais de commande depuis la prose : sans
entrée structurée, un node V0 garde le comportement historique (enveloppe
seule), documenté ci-dessous comme limite connue.
Le verdict d'un node dont l'acceptance est exécutée suit trois issues, jamais une quatrième :
- exécutée, verte — toutes les commandes déclarées ont rendu le code de
sortie attendu (et la sous-chaîne attendue, si
expect_stdout_containsest posé). Le node ferme normalement. - exécutée, rouge — au moins une commande a rendu un code de sortie inattendu, sans qu'aucun signal d'inexécutable (ci-dessous) n'ait été détecté. Suit la cascade normale : réessai au fournisseur suivant du même palier, puis escalade au palier suivant, comme un check d'enveloppe rouge.
- acceptance inexécutable — refus nommé, distinct d'un échec, jamais un
succès : la commande n'a pas pu rendre de verdict exploitable (binaire
introuvable — code de sortie 127 ;
pytestqui rend 5 « no tests collected » ou 4 « usage error » ; une erreur d'import détectée dans la sortie, quel que soit le code de sortie). La cascade s'arrête net sur ce node — changer de fournisseur ou de palier ne répare pas un environnement cassé — etflow statusnomme le node en faute.
La classe V0 exige une acceptance structurée¶
Un node dont le texte seul suffirait à le classer V0 (#309 — « la suite de
tests passe », par exemple) mais qui ne déclare aucune entrée structurée
est rétrogradé en V1 : la cascade démarre à mid (pas cheap), et un
vert ne ferme jamais le node — il le marque à relire
(needs_verification), exactement comme un vrai V1 déclaré. Sans cette
règle, le texte mécanique seul aurait rouvert le fossé même que l'issue #428
corrige : le gate n'aurait toujours que le check d'enveloppe à faire tourner
pour ce node, et fermerait vert sur la seule foi de l'ouvrier — la
rétrogradation, pas seulement le libellé du rapport, est ce qui l'empêche.
Cette dérivation est appliquée une seule fois, au chargement du
blueprint, et transmise à la fois au démarrage de la cascade (run_dispatch)
et au rapport (DispatchExecutor) — flow status et flow run s'accordent
donc sur la même classe pour le même node, jamais recalculée deux fois de
façon divergente. Un avertissement nommé accompagne la rétrogradation, à la
fois dans flow status/le rapport de dispatch et dans les logs :
Le kit n'infère jamais de commande depuis la prose pour éviter cet
avertissement : la seule sortie est de déclarer une entrée structurée
(run/path_exists/test) sur le node.
Un node dont l'acceptance est V1 déclarée (vocabulaire de revue, « revue humaine avant fusion ») n'est pas concerné par cette règle — il n'a jamais prétendu être V0 — et garde le comportement actuel du kit, documenté ici sans être étendu : un vert V1 ferme la cascade en marquant le node à relire, sans qu'aucun juge automatisé n'intervienne. Faire arbitrer une classe V1 par un palier supérieur plutôt que par une revue humaine est hors périmètre de l'issue #428 (voir son texte : « ce que ce ticket refuse »), à traiter par un ticket séparé s'il devient nécessaire.
Dans les deux cas (V1 déclaré, ou V0 rétrogradé), flow status rapporte le
statut d'acceptance « jugée » : le mode conservateur qui ne prétend
jamais à une exécution qui n'a pas eu lieu.
La trace du node (visible dans flow status --output json et le rapport de
flow run --executor dispatch) porte, pour chaque commande exécutée, le code
de sortie et la sortie tronquée à 2 Ko (stdout puis stderr) — de quoi lire un
message d'erreur pytest sans relancer la commande à la main.
Cadrage produit¶
Cinq phases posées sous _grimoire/cadrage/ : brief, brainstorm, compréhension,
exigences, cahier des charges. Le need --needs project-discovery (grimoire
up/grimoire standard init) scaffolde ce dossier par appel de code direct
(cmd_up.py::_step_cadrage), pas par une suggestion textuelle. Détail complet,
sévérités et intégration au gate : docs/cadrage.md.
| Commande | Description |
|---|---|
grimoire cadrage init |
Poser les cinq phases du cadrage |
grimoire cadrage status |
Progression, phase par phase |
grimoire cadrage check |
Gate de complétude : exigences et cahier des charges doivent être renseignés |
Le même gate est aussi visible dans grimoire standard verify/gate/score/
audit : error sur les phases exigences/cahier-des-charges quand le need
project-discovery a été choisi, warning/info sinon (avis, jamais
bloquant).
Cockpit multi-projets¶
Cockpit local de gouvernance, servi sur 127.0.0.1 uniquement. Le registre vit
dans ~/.grimoire/cockpit/registry.json ; grimoire init y inscrit le projet
et l'annonce, et GRIMOIRE_NO_COCKPIT désactive cette inscription.
Le cockpit ne scanne jamais le disque : list lit le registre tel quel,
jamais le système de fichiers. Un projet qui porte les marqueurs Grimoire mais
n'a jamais été enregistré n'apparaît donc pas dans list — ce n'est pas un
défaut de détection, grimoire cockpit list signale « ce dossier ressemble à
un projet Grimoire mais n'est pas enregistré » et donne la commande
grimoire cockpit add <chemin> à lancer.
serve et start font l'exception (#351) : lancés depuis un dossier qui
porte un marqueur Grimoire, ils l'enregistrent automatiquement s'il ne l'était
pas encore et l'ouvrent sélectionné d'emblée — sans cesser d'être
multi-projets, la bascule vers un autre projet reste dans l'UI. C'est
l'intention exprimée en lançant la commande depuis ce dossier qui justifie
l'ajout automatique, pas une décision prise à la place de l'utilisateur : le
registre reste modifiable (remove, prune). Un registre vide, ou un
lancement hors de tout projet Grimoire, nomme grimoire cockpit scan <racine>.
| Commande | Description |
|---|---|
grimoire cockpit add <chemin> |
Enregistrer un projet local |
grimoire cockpit list |
Lister les projets gouvernés |
grimoire cockpit remove <slug> |
Retirer un projet du registre |
grimoire cockpit prune |
Retirer les projets dont le chemin a disparu |
grimoire cockpit scan <racine> |
Découvrir les projets sous une racine et les enrôler |
grimoire cockpit refresh |
Régénérer la couche de données sans servir |
grimoire cockpit serve |
Servir le cockpit (bloquant) |
grimoire cockpit start / stop / status |
Lancer en arrière-plan, arrêter, interroger |
grimoire cockpit open |
Ouvrir le cockpit en cours d'exécution dans le navigateur |
serve, start et open ouvrent workspace/index.html — la même coque que
grimoire serve, avec le niveau Flotte et le sélecteur de projet en plus
(?project=<slug>). portfolio.html (et les autres pages historiques
partagées avec l'atelier) reste servie mais redirige vers l'espace
correspondant ; ?legacy=1 sur l'ancienne URL l'ouvre sans redirection. Voir
l'ADR de la vue de travail.
Workflows¶
Un workflow a une nature. Les commandes d'hygiène (command) doublent un
diagnostic CLI ; les orchestrations (orchestration) coordonnent plusieurs
agents sur plusieurs tours et déclarent parfois l'équipe avec laquelle elles
tournent. Les deux familles vivent dans des répertoires différents — les
premières sous .github/prompts/, les secondes sous le tier kit — et le
catalogue indexe les deux.
| Commande | Description |
|---|---|
grimoire workflows list |
Lister les workflows — nature, agents, provenance |
grimoire workflows list -k orchestration |
Ne garder que les workflows multi-agents |
grimoire workflows list --all |
Inclure ceux qu'une commande CLI remplace |
grimoire workflows teams |
Lister les équipes : membres, spécialité, chaîne de handoff |
grimoire workflows search <terme> |
Chercher par slug, description, et optionnellement contenu |
grimoire workflows show <slug> |
Afficher un workflow, l'équipe qu'il déclare, et son contenu |
grimoire workflows install <slug> |
Installer un workflow du framework — la destination suit sa nature |
grimoire workflows sync |
Synchroniser les prompts du framework vers le projet |
grimoire workflows diff |
Différences entre framework et projet |
grimoire workflows doctor |
Auditer les prompts du projet contre les défauts du framework |
grimoire workflows prune |
Retirer les prompts propres au projet absents du framework |
Workflows remplacés par une commande¶
Quatre des sept prompts livrés redisaient une commande du SDK :
| Workflow | Commande qui le remplace |
|---|---|
/grimoire-status |
grimoire status |
/grimoire-health-check |
grimoire doctor |
/grimoire-self-heal |
grimoire doctor --fix |
/grimoire-pre-push |
grimoire check |
Ils occupaient la moitié du catalogue. Ils restent livrés et installables — un
projet qui les a ne les perd pas — mais ne sont plus déployés dans les projets
neufs ni listés par défaut : --all les montre, avec la commande à utiliser.
Les trois autres restent de plein droit : /grimoire-changelog,
/grimoire-dream et /grimoire-session-bootstrap lisent l'historique et la
mémoire pour en tirer une synthèse, ce qu'aucune commande ne fait.
Se déclarer pour entrer au catalogue¶
Un workflow d'orchestration entre au catalogue en le disant, dans son
frontmatter — pas en étant deviné depuis son emplacement, parce que sous
workflows/ vivent aussi des gabarits de rapport rendus à chaque run :
---
kind: orchestration
description: "Ce que fait ce workflow"
agents: [sm, architect, dev, qa]
team: team-build
triggers:
- la situation qui appelle ce workflow
---
agents, team et patterns sont facultatifs ; description ne l'est pas en
pratique, c'est ce que le catalogue affiche. Un fichier sans frontmatter reste
sur disque et n'est pas listé.
patterns cite les identifiants du catalogue de patterns (ORC-01, KNO-02…)
que le workflow instancie, et memory les couches du Memory OS qu'il lit ou
écrit. Aucun workflow livré ne déclare de couche mémoire : leurs fichiers ne le
disent pas, et l'inventer contredirait la règle du dépôt — ce qui décrit un
artefact doit en être dérivé. Le champ existe pour les workflows que vous
écrivez.
Un prompt qui redit une commande du SDK le déclare avec deprecated_by:,
suivi de la commande.
Utilitaires¶
| Commande | Description |
|---|---|
grimoire context-pack |
Écrire un context-pack durable (contrat catalogue) pour le dépôt |
grimoire update |
Mettre à jour grimoire-kit — alias de grimoire self update |
grimoire debugger status |
État de la réalité et du débogage des agents |
grimoire debugger claims |
Affirmations enregistrées par les agents |
grimoire debugger plan |
Plan de débogage courant |
grimoire debugger generate |
Générer les artefacts de débogage |
grimoire debugger serve |
Servir la vue de débogage |
L'alias court grimoire dbg existe pour debugger.
Sous-commandes¶
grimoire config show¶
Affiche la configuration du projet (lecture seule).
- Sans argument : affiche le YAML complet
- Avec clé dot-notation :
grimoire config show project.name - Avec
--output json: sortie JSON
grimoire config get¶
Récupère une valeur de configuration par clé dot-notation.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire config path¶
Affiche le chemin résolu vers project-context.yaml.
grimoire config set¶
Modifie une valeur de configuration par dot-notation.
| Option | Description |
|---|---|
--dry-run, -n |
Affiche la modification sans l'appliquer |
--output, -o |
Format de sortie : text ou json |
Exemples :
grimoire config set project.name "mon-projet"
grimoire config set memory.backend qdrant-local --dry-run
grimoire -o json config set project.description "My app"
Note : les valeurs de type liste ne peuvent pas être définies via
config set. Utilisezgrimoire config editpour modifier directement le fichier YAML.
grimoire config list¶
Liste toutes les clés de configuration avec leurs valeurs actuelles.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text (table Rich) ou json |
grimoire config edit¶
Ouvre project-context.yaml dans l'éditeur système.
Utilise $VISUAL, puis $EDITOR, puis vi par défaut.
grimoire config validate¶
Valide le fichier project-context.yaml contre le schéma Grimoire.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json ({valid, warnings}) |
Code de sortie 1 si la configuration est invalide.
grimoire self version¶
Affiche la version installée et vérifie les mises à jour sur PyPI.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire self diagnose¶
Exécute un auto-diagnostic de l'installation grimoire-kit.
Vérifie : dépendances requises/optionnelles, version Python, entry point CLI.
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire registry list¶
Liste les agents disponibles dans les archétypes installés.
grimoire registry search¶
Recherche un agent par mot-clé.
grimoire registry dispatches¶
Compte les choix d'agent (#366) et les non-choix (#389) observés, lus dans le TraceLedger du projet — pas la carte statique des agents déclarés.
Deux tableaux : les agents réellement choisis comme persona d'entrée (combien de fois, la dernière fois), et les spécialités cherchées sans spécialiste trouvé (même forme). Voir Persona d'entrée → Non-choix.
grimoire agent-miss¶
Journalise un non-choix : le concierge a cherché un spécialiste et n'en a trouvé aucun, ou s'est rabattu sur un généraliste.
grimoire agent-miss --category tests
grimoire agent-miss --category infra --specialty terraform \
--fallback backend-engineer --reason "aucun agent terraform déclaré"
| Option | Description |
|---|---|
--category |
Catégorie de la demande telle que comprise (obligatoire, jamais son contenu) |
--specialty |
Spécialité cherchée, si elle est nommable |
--fallback |
Agent de repli retenu, s'il y en a un |
--reason |
Pourquoi aucun spécialiste ne convenait |
Appelée par la persona concierge (archetypes/meta/agents/concierge.md), pas
par du code du kit : cette résolution se fait dans son raisonnement. Écriture
best-effort — un journal indisponible ou illisible ne fait jamais échouer la
commande. Détail : Persona d'entrée → Non-choix.
grimoire proposals¶
Le déclencheur d'artefact (issue #395) : à la répétition d'une même spécialité manquante (jamais au premier non-choix), propose un agent — ou un skill à attacher à un porteur existant — mais ne crée jamais rien sans acceptation explicite.
grimoire proposals list
grimoire proposals accept terraform-specialist
grimoire proposals reject terraform-specialist
grimoire -o json proposals list
| Commande | Description |
|---|---|
grimoire proposals list |
Propositions en attente, rafraîchies depuis grimoire registry dispatches |
grimoire proposals accept <slug> |
Écrit l'artefact réel dans _grimoire/overrides/ (même chemin que l'outil d'ajout d'agent) |
grimoire proposals reject <slug> |
Marque la proposition refusée — reproposée seulement si son compte double depuis ce refus |
Seuil configurable via proposals.threshold dans project-context.yaml
(défaut 2, jamais 1). Aucune option --auto : accepter reste toujours un
geste explicite. Même moteur que le cockpit (espace Piloter, section
Agents), qui montre et actionne les mêmes propositions.
Choix du porteur (issue #402) — la persona d'entrée du projet (le
concierge, ou l'agent que agents.entry désigne dans
project-context.yaml) route les demandes vers un spécialiste ; elle n'en
exécute aucune elle-même, donc elle n'est jamais retenue comme porteuse d'un
skill, même quand c'est elle que le ledger enregistre comme agent de repli
(grimoire agent-miss --fallback ...). La colonne « Porteur » de
grimoire proposals list (et le champ target_agent en JSON) montre
l'agent réellement retenu, distinct au besoin du fallback_agent brut ; la
colonne « Raison » (carrier_reason) explique le choix :
carrier_reason |
Sens |
|---|---|
repli observé |
Le repli enregistré n'est pas la persona d'entrée — il est utilisé tel quel |
porteur par catégorie : <agent> |
Le repli était vide ou était la persona d'entrée ; exactement un agent déclaré couvre la catégorie observée (use_when, ou faisceau execute pour une catégorie d'exécution) |
persona d'entrée exclue, aucun porteur : agent |
Le repli était vide ou était la persona d'entrée, et zéro ou plusieurs agents couvrent la catégorie — la proposition devient un agent plutôt qu'un skill ambigu |
grimoire plugins list¶
Liste les plugins installés (tools et backends).
| Option | Description |
|---|---|
--output, -o |
Format de sortie : text ou json |
grimoire completion install¶
Installe l'auto-complétion pour le shell.
grimoire completion export¶
Exporte le script de complétion vers stdout (pour piping/redirection).
grimoire completion export --shell bash > ~/.local/share/bash-completion/grimoire
grimoire completion export --shell zsh > _grimoire
Utile pour la configuration dotfiles et les environnements CI.
Gestion de projet¶
grimoire add¶
Ajoute un agent au projet.
| Option | Description |
|---|---|
--dry-run, -n |
Affiche le plan sans modifier la configuration |
grimoire remove¶
Retire un agent du projet.
| Option | Description |
|---|---|
--dry-run, -n |
Affiche le plan sans modifier la configuration |
Confirmation
La commande remove demande une confirmation interactive. Utilisez --yes/-y pour la bypasser (CI/scripting), ou -o json (confirmation implicite).
Migre la structure du projet vers la dernière version.
grimoire merge¶
Fusionne la configuration de deux projets.
Confirmation
merge --undo demande une confirmation interactive. Utilisez --yes/-y pour la bypasser.
grimoire history¶
Affiche l'historique des opérations CLI récentes (audit trail).
| Option | Description | Défaut |
|---|---|---|
--limit, -n |
Nombre d'entrées à afficher | 20 |
--filter, -f |
Filtrer par nom de commande (ex: add, init) |
— |
--output, -o |
Format de sortie : text ou json |
text |
Les opérations sont enregistrées automatiquement dans _grimoire/_memory/.grimoire-audit.jsonl lors de l'exécution de init, add, remove, config set, upgrade, et merge.
grimoire setup¶
Synchronise l'identité du projet — utilisateur, langues, niveau — entre
project-context.yaml, la source de vérité, et les fichiers qui la reflètent
(.github/copilot-instructions.md).
grimoire setup [PATH] --check # audit seul, sortie 1 si un miroir diverge
grimoire setup [PATH] --sync # réécrire les miroirs depuis project-context.yaml
grimoire setup [PATH] --user Guilhem --skill-level expert --lang Français --doc-lang Français
Une option écrit d'abord la section user: de project-context.yaml — créée
si le projet est antérieur à son introduction — puis les miroirs ; la
vérification finale relit le fichier et compare les miroirs à lui. Un
« All config files are in sync » n'est donc annoncé que s'il est vrai.
grimoire repair¶
Auto-réparation des problèmes courants détectés par grimoire doctor.
| Option | Description | Défaut |
|---|---|---|
--dry-run, -n |
Prévisualise sans modifier | False |
--output, -o |
Format de sortie : text ou json |
text |
Actions de réparation :
- Création des répertoires manquants (_grimoire/, _grimoire-output/, _grimoire/_memory/)
- Nettoyage des entrées d'audit de plus de 90 jours
Flags globaux¶
| Flag | Description |
|---|---|
--version, -V |
Affiche la version et quitte |
--verbose, -v |
Augmente la verbosité (-v = INFO, -vv = DEBUG) |
--quiet, -q |
Supprime les sorties hors erreurs |
--no-color |
Désactive la coloration (utile en CI) |
--log-format |
Format des logs : text ou json |
--output, -o |
Format de sortie : text ou json |
--time |
Affiche le temps d'exécution en ms |
--profile |
Affiche le breakdown timing par phase (arbre Rich) |
--yes, -y |
Saute les confirmations interactives |
--help |
Affiche l'aide |
Sortie JSON pour le scripting¶
La plupart des commandes supportent --output json (ou -o json) pour une sortie machine-readable.
| Commande | JSON | Exemple |
|---|---|---|
status |
✓ | grimoire -o json status . \| jq .project |
init |
✓ | grimoire -o json init myproject |
doctor |
✓ | grimoire -o json doctor . \| jq .failed |
validate |
✓ | grimoire -o json validate . \| jq .valid |
check |
✓ | grimoire -o json check . \| jq .all_ok |
lint |
✓ | grimoire lint . --format json \| jq .count |
diff |
✓ | grimoire -o json diff . |
env |
✓ | grimoire -o json env |
version |
✓ | grimoire -o json version |
config show |
✓ | grimoire -o json config show . |
config get |
✓ | grimoire -o json config get project.name |
config set |
✓ | grimoire -o json config set project.name "new" |
config list |
✓ | grimoire -o json config list |
config validate |
✓ | grimoire -o json config validate |
add |
✓ | grimoire -o json add my-agent . |
remove |
✓ | grimoire -o json remove my-agent . |
self version |
✓ | grimoire -o json self version |
self diagnose |
✓ | grimoire -o json self diagnose |
registry list |
✓ | grimoire -o json registry list |
registry search |
✓ | grimoire -o json registry search web |
plugins list |
✓ | grimoire -o json plugins list |
up |
✓ | grimoire -o json up . |
upgrade |
✓ | grimoire -o json upgrade . |
schema |
✓ | grimoire schema (toujours JSON) |
history |
✓ | grimoire -o json history -n 50 |
repair |
✓ | grimoire -o json repair . |
Variables d'environnement¶
| Variable | Description |
|---|---|
GRIMOIRE_DEBUG |
1 pour activer le traceback complet sur erreur |
GRIMOIRE_LOG_LEVEL |
Niveau de log (DEBUG, INFO, WARNING, ERROR) |
GRIMOIRE_LOG_FORMAT |
Format de log (text, json) |
GRIMOIRE_OUTPUT |
Format de sortie par défaut (json pour l'activer sans -o json) |
GRIMOIRE_QUIET |
1 ou true pour activer le mode silencieux sans --quiet |
NO_COLOR |
Toute valeur non vide désactive la couleur (no-color.org) |
GRIMOIRE_OFFLINE |
1 ou true pour forcer le mode hors-ligne (pas de vérification réseau) |
Organisation de l'aide¶
Les commandes sont regroupées par catégorie dans grimoire --help :
| Panneau | Commandes |
|---|---|
| Project | init, doctor, status, up |
| Agents | add, remove, agent-miss, registry |
| Validation | validate, lint, check, schema |
| Configuration | config, diff |
| Utilities | upgrade, merge, setup, repair, completion, plugins |
| Info | version, env, self, history |
Codes d'erreur¶
Les erreurs Grimoire incluent un code stable et une suggestion de récupération :
| Code | Signification | Action suggérée |
|---|---|---|
GR001 |
Erreur de configuration YAML | grimoire validate |
GR002 |
Projet non initialisé | grimoire init <path> |
GR003 |
Agent introuvable | grimoire registry search <name> |
GR004 |
Erreur d'exécution d'un outil | grimoire doctor |
GR005 |
Conflit de merge non résolu | Résolution manuelle puis retry |
GR010 |
Erreur réseau | Vérifier la connexion |
GR050 |
Erreur de validation schéma | grimoire validate |
grimoire ext¶
Gestion des extensions (bundles d'artefacts gouvernés). Voir Extensions & marketplace.
| Commande | Rôle |
|---|---|
grimoire ext add <dossier> |
Installer depuis un dossier local |
grimoire ext add <id> --registry <clone> [--version X.Y.Z] |
Installer depuis le registry, checksum vérifié |
grimoire ext list |
Extensions installées et leurs patterns |
grimoire ext verify <id> |
Vérification post-installation |
grimoire ext remove <id> |
Désinstallation (hooks retirés du registre de sécurité) |
grimoire ext publish <source> --registry <clone> |
Publier une extension ou un .blueprint.json |
grimoire ext add-blueprint <id> --registry <clone> |
Installer un blueprint publié |
grimoire serve (alias déprécié)¶
grimoire serve est un alias de grimoire cockpit serve
(#351) : les deux commandes ouvraient la même UI, l'une en mono-projet, l'autre
en multi-projets — cockpit serve fait maintenant les deux, en s'ouvrant
directement sur le projet courant quand on le lance depuis un projet Grimoire.
serve reste utilisable pour ne pas casser les scripts existants ; il affiche
un avertissement et délègue à cockpit serve. --project-root est ignoré :
lancer la commande depuis le projet visé suffit.
Pour une UI custom ou une racine de kit explicite (--ui-dir, --kit-root),
utiliser la forme longue : python -m grimoire.tools.forge_server.
La vue de travail, page par défaut¶
--open ouvre workspace/index.html — la coque unique décrite par
web/DESIGN-SPEC-workspace-2026-09.md et son
ADR. Les pages historiques
(atelier.html, kanban.html, observability.html, memory.html,
blueprints.html, patterns.html, extensions.html, labs.html,
documentation.html) restent servies mais redirigent désormais vers l'espace
de la coque qui les remplace ; ajouter ?legacy=1 à l'URL sert encore
l'ancienne page, sans redirection.
Source : IntelliSense déterministe (issue 280)¶
L'éditeur de l'espace Source colorie le frontmatter, les blocs <agent>/
<activation>/<step>, les placeholders ({project-root}, {{…}}) et les
identifiants d'agents, de patterns et de workflows, sans dépendance ni
bundler (surcouche par recouvrement sur la <textarea>, voir
ADR-006 D2). Un correcteur signale un chemin du
kit qui ne se résout pas (même logique que grimoire doctor), un agent
routé mais absent du manifeste, une clé de frontmatter inconnue, un terme du
glossaire cité mais non défini, ou un pattern/workflow inconnu du catalogue —
recalculé à l'enregistrement et au repos de saisie, et repris dans l'onglet
Problèmes du dock. La complétion (Ctrl+Espace, ou déclenchée par {, @,
/) propose agents, workflows, patterns, chemins du kit et clés de schéma ;
le survol d'un identifiant lié à une entrée du glossaire ouvre la même bulle
épinglable que le reste de la vue de travail. Tout vient de
GET /api/workspace/language (src/grimoire/tools/workspace_language.py),
servi en lecture seule sur les deux hôtes — voir le tableau des routes dans
web/workspace/README.md.
Source : suggestions par modèle local (issue 280, voie 2)¶
Derrière cette IntelliSense déterministe, jamais à sa place : un petit
modèle local (Ollama) peut proposer du texte — compléter une clause
d'emploi (use_when/dont_use_when), rédiger le corps d'un agent ou d'une
étape de workflow, expliquer un diagnostic — mais ne fait jamais autorité sur
les identifiants, les chemins ou les diagnostics, qui restent ceux de
workspace_language.py. Deux conditions cumulatives, sinon l'interface ne
montre rien et ne tente rien :
- le doctor voit Ollama sur le poste (même sonde que
grimoire providers audit—GET /api/tags, sans dépenser de quota) ; project-context.yamldéclaresource.assist.model: "<modèle>"— vide par défaut. Le modèle se choisit parmi ceux réellement présents (ollama list) ;qwen3-coder:30b, ou le plus petit modèle codeur trouvé, est un défaut raisonnable.
GET /api/workspace/assist (sans coût, jamais d'appel au modèle) dit si le
bouton Suggérer de l'éditeur doit apparaître ; POST /api/workspace/assist
(chemin, texte, position, intention) l'appelle réellement, avec un délai
borné à 10 s. La réponse porte la suggestion brute du modèle et la liste
de ce qu'elle cite sans figurer dans le paquet de langage (agent, workflow,
pattern ou chemin) — jamais corrigée à la place de l'utilisateur, seulement
marquée « inconnu ». Le panneau d'aperçu (Ctrl+Maj+Espace, ou le bouton
Suggérer) affiche cette suggestion à côté de l'éditeur ; Insérer la
place au curseur par le même chemin que la frappe clavier (colorisation et
diagnostics se recalculent dessus), Ignorer referme le panneau sans rien
écrire. Aucun envoi automatique à la frappe, aucun fournisseur distant,
aucune clé, aucune donnée hors de la machine — le module
src/grimoire/tools/source_assist.py ne contacte jamais qu'Ollama en local.
Si l'URL Ollama résolue (OLLAMA_HOST) ne pointe pas vers une adresse de
bouclage, l'appel est refusé (nommé) sauf déclaration explicite de
source.assist.allow_lan: true.
Un modèle qui n'est pas encore chargé en mémoire (GET /api/ps) n'est pas
une panne : GET /api/workspace/assist le déclenche lui-même en tâche de
fond (un préchauffage sans génération) et répond « chargement du modèle,
réessayez dans quelques secondes » — le bouton Suggérer reste visible
mais désactivé, et l'éditeur re-sonde le statut toutes les 3 s jusqu'à ce
qu'il devienne prêt. Le délai de 10 s ci-dessus ne s'applique qu'à un modèle
déjà résident (issue #450).
Projets de la machine¶
Le bouton de projet, en haut de la barre latérale, ouvre le sélecteur. Trois entrées, parce qu'il y a trois situations :
| Entrée | Ce qu'elle fait |
|---|---|
| Liste | Les projets déjà connus de la machine (registre partagé avec grimoire cockpit). Un clic re-route le serveur sur le projet choisi. |
| Parcourir | Navigation dossier par dossier depuis $HOME, ou chemin absolu collé. Les projets sont signalés au passage. |
| Scanner | Parcours borné d'une racine (profondeur 4 par défaut). Le scan propose : rien n'est enrôlé sans sélection explicite. |
Le projet servi est enrôlé au registre à l'ouverture, s'il porte un marqueur
(.git, project-context.yaml, _grimoire/). Ouvrir un projet n'écrit rien
dans son arbre : registre et couche de données vivent sous
~/.grimoire/. Purger les entrées mortes : grimoire cockpit prune.
Données affichées : celles du projet, ou rien¶
Observatoire, Mémoire et Kanban lisent une couche générée sur le projet
servi (gen-site-data.py, régénérée en arrière-plan au démarrage et à chaque
changement de projet). Tant qu'elle n'existe pas, ces pages sont vides et le
disent.
Le site embarqué dans la wheel contient aussi l'instantané de la vitrine publique — des projets de démonstration et les chiffres du dépôt du kit. Il n'est jamais servi en local : afficher 141 entrées mémoire et des traces d'agents vieilles de deux minutes pour un projet qui n'a rien lancé est pire qu'une page vide. Seules les références du kit (catalogue de patterns, marketplace, anatomie) restent servies telles quelles.
L'état de la couche est visible sur le tableau de bord, chip données ; un
clic la régénère (POST /api/data/refresh).
grimoire features¶
Canaux de features : stable (contrat SemVer), beta (opt-in par projet,
journalisées, promues sur métriques d'usage), experimental (surface R&D).
État persisté dans _grimoire/features.json. La page Labs de l'atelier
(grimoire serve) expose les mêmes bascules.
| Sous-commande | Rôle |
|---|---|
list |
Lister les features à canal et leur état pour le projet |
enable <id> · disable <id> |
Basculer une feature beta (certaines portent une action réelle, ex. stigmergy-hooks installe/retire les hooks) |
grimoire stigmergy (beta)¶
Coordination indirecte par phéromones (canal beta — voir
R&D expérimental). Tableau local _grimoire-output/pheromone-board.json.
| Sous-commande | Rôle |
|---|---|
emit --type --location --text --agent [--tags] [--intensity] |
Déposer un signal typé (NEED, ALERT, OPPORTUNITY, PROGRESS, COMPLETE, BLOCK) |
sense [--type] [--location] [--json] |
Détecter les signaux actifs (au-dessus du seuil) |
amplify --id --agent · resolve --id --agent |
Renforcer / résoudre un signal |
trails |
Patterns émergents (hot-zone, convergence, bottleneck, relay) |
evaporate [--dry-run] · stats |
Purge des signaux morts / statistiques |
install-hooks · uninstall-hooks |
Câbler / retirer l'émission + captation automatiques |
Chaque sous-commande accepte --project-root (défaut : dossier courant).
L'intensité décroît par demi-vie (72 h), calculée à la lecture — aucun démon.
Boucle vivante (hooks)¶
grimoire stigmergy install-hooks rend le système autonome, en copiant trois
hooks non bloquants dans .github/hooks/ du projet :
- SessionStart — injecte les signaux actifs dans le contexte de l'agent.
- PostToolUse — une édition dépose (ou renforce, anti-bruit) un signal
PROGRESSsur la zone touchée. - Stop — marque
COMPLETEla zone la plus active et purge les signaux morts.
Ces hooks sont safe par construction : ils n'émettent que du contexte ou
rien, jamais de décision de blocage. S'il existe, ils sont journalisés en
mode shadow dans _grimoire-runtime/_config/hook-safety-registry.json.