Catalogue d'expertises — langages, ingénierie, cloud¶
Issue #616. Ce document est la
référence API du mécanisme : ce qu'un appelant (le wizard d'onboarding de la PR 3, le cockpit, un
script) peut attendre de grimoire.core.expertises et de grimoire expertise, et comment le
mécanisme s'articule avec les tiers kit/overrides existants.
Le principe : rien d'attaché par défaut, sauf choix ou détection¶
Le kit livre par archétype un agent généraliste (stack-engineer, ops-engineer) plus les skills
qu'il attache d'emblée. Le catalogue d'expertises ajoute une troisième couche, optionnelle : un
langage bas niveau, un patron d'architecture, un fournisseur cloud — que l'utilisateur choisit
explicitement ou que la détection recommande, jamais attaché d'office. La raison est chiffrée dans
la doctrine des artefacts : un skill non référencé
par un agent devient transversal (chargé à chaque tour de la session, par tous les agents),
alors qu'un skill attaché ne coûte que sur les tours où son agent porteur travaille.
Ce même principe a corrigé un défaut du mécanisme historique (issue #375) : les sept skills
stack-python/stack-go/stack-typescript/stack-docker/stack-terraform/stack-ansible/
stack-k8s s'attachaient en bloc dès que l'archétype stack était installé, qu'ils servent ou
non — un projet Python nu payait six skills transversaux pour rien. Depuis cette issue, seule la
détection réelle du projet (grimoire.core.scanner.StackScanner) décide du sous-ensemble attaché
par défaut ; le reste s'ajoute à la demande via ce même catalogue (voir
grimoire.core.stack_skills.detected_stack_skill_slugs, appelé par ProjectScaffolder dans src/grimoire/core/scaffold.py).
Le wizard en trois questions — l'archétype est déduit¶
Depuis l'issue #888 (décision consignée dans #630), grimoire init interactif ne demande plus un
archétype — c'est un vocabulaire interne du kit, pas celui d'un nouvel utilisateur — ni un choix
libre de skills. Il pose trois questions, pré-remplies par la détection (StackScanner,
ArchetypeResolver, marqueurs du registre), et déduit le reste :
| Question | Réponses | Ce qu'elle décide |
|---|---|---|
| Quelle pile technique ? (plusieurs réponses) | Python, JavaScript/TypeScript, Go, Rust, Java/Kotlin, C#, Ruby, Docker, Terraform, Kubernetes, Ansible | les skills stack-* attachés à Atlas pour les piles qui en ont un ; les expertises du registre recommandées (pas attachées) pour les autres (rust, java…) ; la pile que le scaffold croit (une pile cochée sans marqueur est déclarée, une pile détectée mais décochée disparaît) |
| Qui travaille sur le projet ? | moi seul (je connais ma pile), moi seul (j'apprends), une petite équipe, une équipe avec des gens ops/plateforme, surtout des agents que je supervise | le niveau d'accompagnement (skill_level) ; les besoins du standard agentique et le profil qu'ils imposent (solo-prototyping → starter, hooks-skills-governance, multi-agent-orchestration…) ; infra-ops ajouté quand des gens ops travaillent sur une pile infra déclarée |
| De quoi parle le projet ? | une bibliothèque, un CLI, un service ; une application web ; de l'infrastructure ; une plateforme interne ; du contenu ; une maintenance avec boucle de correction certifiée ; le standard agentique lui-même | l'archétype : stack, web-app, infra-ops, platform-engineering, creative-studio, fix-loop, agentic-standard |
Le résumé avant installation montre ce qui a été déduit — pile, archétype, niveau, profil du
standard, skills, expertises, hôtes, cockpit, langue, mémoire — et s'ajuste en une ligne
(domain=web who=team stack=python,go). grimoire init -y garde la détection seule, sans
question : c'est exactement ce que les réponses pré-remplies auraient donné. Une supposition du
résolveur (is_best_guess, décision du 2026-09-18) n'est jamais pré-remplie comme une détection.
Un projet Python nu qui répond « Entrée » partout reçoit stack + stack-python, et rien
d'autre : l'entrée python du registre est déjà ce skill, aucune expertise n'est attachée d'office.
grimoire up --interactive reprend les besoins déduits pour le standard quand --needs n'est pas
donné.
La logique vit dans src/grimoire/cli/init_questions.py (fonctions pures, sans terminal) ; la CLI
et l'assistant de configuration du cockpit (GET /api/setup/questions, espace Piloter) appellent
les mêmes fonctions, donc une même réponse donne le même archétype des deux côtés.
Le registre — registry/expertises.yaml¶
Trois familles, chacune une liste d'entrées :
| Famille | Contenu | Détection |
|---|---|---|
languages |
Python, TypeScript, Go (skills stack-* réutilisés tels quels), Rust, C, C++, C#, Java, Kotlin, Swift, PHP, Ruby, Scala, Elixir |
Marqueurs de fichiers, ou StackScanner pour les langages qu'il connaît déjà |
engineering |
Design patterns, architecture haut niveau, systèmes bas niveau, testing avancé, sécurité applicative, performance | Aucune — transversal, jamais recommandé automatiquement |
cloud |
AWS, Azure, GCP, OVHcloud, Hetzner, Cloudflare, Scaleway, Kubernetes managé (EKS/AKS/GKE) | Marqueurs de fichiers et/ou bloc provider "<nom>" {} dans les *.tf |
Chaque entrée :
- id: rust # identifiant stable, utilisé par le CLI et l'API
name: "Rust" # nom affiché
summary: "Une phrase." # résumé affiché par `expertise list`
skill: "framework/expertises/skills/expertise-rust.md" # chemin relatif à la racine kit
porteur: stack-engineer # agent visé par défaut
porteur_fallback: stack-engineer # optionnel — utilisé si `porteur` est absent du projet
detect: # optionnel — absent = jamais recommandé automatiquement
stack_scanner: rust # réutilise StackScanner (mêmes marqueurs qu'à l'init)
files: ["Cargo.toml"] # marqueurs vérifiés directement (fichiers, globs, dossiers en `/`)
terraform_providers: ["aws"] # bloc `provider "aws" {}` dans un `*.tf` du projet
skill pointe soit un skill archetypes/stack/skills/stack-*.md déjà existant (les sept ne sont
jamais dupliqués), soit un nouveau skill sous framework/expertises/skills/ — cette seconde
racine n'est jamais copiée en bloc par le scaffolder (contrairement à archetypes/*/skills/) :
un skill n'y devient effectif pour un projet que via grimoire expertise add.
porteur_fallback couvre le cas cloud sur un projet sans infra-ops : expertise add aws sur un
projet stack-seul attache le skill à stack-engineer plutôt que d'échouer.
API Python — grimoire.core.expertises¶
from pathlib import Path
from grimoire.core.expertises import load_catalog, detect_expertises, attach_expertise, detach_expertise
catalog = load_catalog() # tuple[Expertise, ...], ordre du registre
recommendations = detect_expertises(Path("."), catalog=catalog) # list[Recommendation], jamais de mutation
by_id = {e.id: e for e in catalog}
result = attach_expertise(Path("."), by_id["rust"]) # AttachResult — écrit l'override, valide, ou lève
detach_expertise(Path("."), by_id["rust"]) # DetachResult — retire le slug ET le fichier de skill
Expertise.resolve_porteur(project_root)— l'agent porteur effectif pour ce projet (porteur, sinonporteur_fallback, sinonGrimoireAgentErrornommée : jamais un attachement silencieux à un agent absent).Recommendationporteid,name,family,reason(texte humain, jamais vide) etconfidence(0.0–1.0). Une expertise sans signal présent n'apparaît pas dans la liste — il n'y a pas de recommandation à confiance nulle.attach_expertise/detach_expertisevalident toujours viagrimoire.hosts.collect.collect_agents/collect_skillsavant de considérer l'écriture définitive ; un échec de résolution restaure l'état précédent (même discipline quegrimoire.core.override_drift.convert_override). Idempotents : attacher deux fois ne duplique rien (AttachResult.already_attached), détacher une expertise jamais attachée est un no-op nommé (DetachResult.was_attached is False).
Contrat de stabilité (pour la PR 3 — étape « Expertises » du wizard) : les noms de fonctions,
les champs de Expertise/Recommendation/AttachResult/DetachResult et le format du registre
sont la surface publique de ce module. Un appelant peut lister le catalogue, appeler
detect_expertises pour pré-cocher les recommandations, laisser l'utilisateur ajuster la sélection,
puis appeler attach_expertise pour chaque id retenu — sans jamais lire ou écrire directement sous
_grimoire/.
CLI — grimoire expertise¶
grimoire expertise list # tout le catalogue, groupé par famille
grimoire expertise list --detected # seulement ce que la détection recommande, avec raison
grimoire expertise add rust aws # attache (override projet, jamais _grimoire/kit/)
grimoire expertise remove rust # détache (retire aussi le fichier de skill)
add/remove n'invoquent pas grimoire host sync elles-mêmes (même séparation des responsabilités
que grimoire agent override convert) — lancez-le ensuite pour projeter le changement sur les
hôtes configurés. grimoire up conserve la sélection : elle vit sous _grimoire/overrides/, un
tier que up ne régénère jamais.
Mécanique d'attachement — ce que add/remove écrivent¶
- Le corps du skill est copié depuis le paquet kit (
archetypes/stack/skills/ouframework/expertises/skills/) vers_grimoire/overrides/skills/<slug>.md. - Le porteur reçoit un override partiel (
extends: kit) sous_grimoire/overrides/agents/<porteur>.md, avec le slug ajouté (ou retiré) de son champskills:— le même mécanisme quegrimoire agent override convert(grimoire.core.override_drift), une simple redéfinition de champ de frontmatter, jamais une copie intégrale de l'agent. detach_expertisesupprime aussi le fichier de skill de l'étape 1 — le garder sans qu'aucun agent le référence le rendrait transversal, un état pire que l'attachement qu'on voulait défaire.
État de la couverture¶
28 des 28 entrées ont un skill livré (25 nouveaux sous framework/expertises/skills/, plus
stack-python/stack-typescript/stack-go réutilisés tels quels, issue #616). Une seule entrée
n'a pas encore de détection fiable : kubernetes-managed (distinguer une ressource de cluster
managé d'un simple provider aws/azurerm/google utilisé pour autre chose demande un détecteur
par nom de ressource Terraform, pas encore écrit) — le skill existe, l'attachement manuel
(grimoire expertise add kubernetes-managed) fonctionne, seule la recommandation automatique reste
une issue de suivi.
Voir aussi : Doctrine — quand créer un artefact (le coût d'un skill non
attaché), Créer un agent, tests/unit/core/test_expertises_catalog.py (le
contrat que chaque entrée doit tenir).