/understand-domain
Extrait les connaissances du domaine métier — domaines, flux métier et étapes de processus — d'une base de code et produit un graphe de flux horizontal interactif dans le tableau de bord.
Fonctionnement
- Si un graphe de connaissances existe déjà (
.ua/knowledge-graph.json, ou.understand-anything/knowledge-graph.jsonen version legacy quand ce répertoire est présent), en dérive les connaissances du domaine (économique, sans analyse de fichiers) - Si aucun graphe de connaissances n'existe, effectue une analyse légère : arborescence de fichiers + détection de points d'entrée + fichiers échantillonnés
- Utilise le drapeau
--fullpour forcer une nouvelle analyse même si un graphe de connaissances existe
Instructions
Phase 0 : Résoudre PROJECT_ROOT
Définis PROJECT_ROOT au répertoire de travail actuel.
Redirection worktree. Si PROJECT_ROOT se trouve à l'intérieur d'une git worktree (pas le checkout principal), redirige la sortie vers la racine du dépôt principal. Les worktrees gérées par Claude Code sont éphémères — le répertoire de données (.ua/, ou legacy .understand-anything/) écrit dedans est détruit à la fin de la session, supprimant aussi le graphe de domaine (issue #133). Détecte une worktree en comparant git rev-parse --git-dir avec git rev-parse --git-common-dir ; dans un checkout normal ou un submodule ils se résolvent au même chemin, dans une worktree ils diffèrent et le parent de --git-common-dir est la racine du dépôt principal.
COMMON_DIR=$(git -C "$PROJECT_ROOT" rev-parse --git-common-dir 2>/dev/null)
GIT_DIR=$(git -C "$PROJECT_ROOT" rev-parse --git-dir 2>/dev/null)
if [ -n "$COMMON_DIR" ] && [ -n "$GIT_DIR" ]; then
COMMON_ABS=$(cd "$PROJECT_ROOT" && cd "$COMMON_DIR" 2>/dev/null && pwd -P)
GIT_ABS=$(cd "$PROJECT_ROOT" && cd "$GIT_DIR" 2>/dev/null && pwd -P)
if [ -n "$COMMON_ABS" ] && [ "$COMMON_ABS" != "$GIT_ABS" ]; then
MAIN_ROOT=$(dirname "$COMMON_ABS")
if [ -d "$MAIN_ROOT" ] && [ "${UNDERSTAND_NO_WORKTREE_REDIRECT:-0}" != "1" ]; then
echo "[understand-domain] Detected git worktree at $PROJECT_ROOT"
echo "[understand-domain] Redirecting output to main repo root: $MAIN_ROOT"
echo "[understand-domain] (Set UNDERSTAND_NO_WORKTREE_REDIRECT=1 to keep PROJECT_ROOT as the worktree.)"
PROJECT_ROOT="$MAIN_ROOT"
fi
fi
fi
Utilise $PROJECT_ROOT (et non le répertoire actuel brut) pour chaque référence au « projet actuel » / <project-root> dans les phases suivantes.
Résoudre le répertoire de données $UA_DIR. Tous les artefacts Understand-Anything se trouvent dans le répertoire de données du projet. Résous-le une fois, maintenant que $PROJECT_ROOT est connu, et réutilise $UA_DIR pour chaque lecture et écriture dans les phases suivantes :
UA_DIR="$PROJECT_ROOT/$([ -d "$PROJECT_ROOT/.understand-anything" ] && echo .understand-anything || echo .ua)"
Cela préserve le répertoire legacy .understand-anything/ s'il existe déjà (les projets existants continuent de fonctionner sans migration) et utilise le nouveau .ua/ sinon. Comme chaque phase peut s'exécuter dans un shell frais, porte $UA_DIR en avant comme $PROJECT_ROOT, en le re-résolvant avec la ligne ci-dessus si un bloc de commande ultérieur l'utilise.
Important : ne présume pas que la racine du plugin est simplement deux répertoires au-dessus du chemin d'accès de la skill. Dans nombreuses installations ~/.agents/skills/understand-domain est un lien symbolique vers le vrai checkout du plugin. Préfère d'abord les racines de plugin fournies au runtime (pour Claude), puis reviens à des liens symboliques universels, la résolution de liens symboliques de skill, et les chemins d'installation courants basés sur des clones.
Résous la racine du plugin comme suit :
SKILL_REAL=$(realpath ~/.agents/skills/understand-domain 2>/dev/null || readlink -f ~/.agents/skills/understand-domain 2>/dev/null || echo "")
SELF_RELATIVE=$([ -n "$SKILL_REAL" ] && cd "$SKILL_REAL/../.." 2>/dev/null && pwd || echo "")
COPILOT_SKILL_REAL=$(realpath ~/.copilot/skills/understand-domain 2>/dev/null || readlink -f ~/.copilot/skills/understand-domain 2>/dev/null || echo "")
COPILOT_SELF_RELATIVE=$([ -n "$COPILOT_SKILL_REAL" ] && cd "$COPILOT_SKILL_REAL/../.." 2>/dev/null && pwd || echo "")
PLUGIN_ROOT=""
for candidate in \
"${CLAUDE_PLUGIN_ROOT}" \
"$HOME/.understand-anything-plugin" \
"$SELF_RELATIVE" \
"$COPILOT_SELF_RELATIVE" \
"$HOME/.codex/understand-anything/understand-anything-plugin" \
"$HOME/.opencode/understand-anything/understand-anything-plugin" \
"$HOME/.pi/understand-anything/understand-anything-plugin" \
"$HOME/understand-anything/understand-anything-plugin"; do
if [ -n "$candidate" ] && [ -f "$candidate/package.json" ] && [ -f "$candidate/pnpm-workspace.yaml" ]; then
PLUGIN_ROOT="$candidate"
break
fi
done
if [ -z "$PLUGIN_ROOT" ]; then
echo "Error: Cannot find the understand-anything plugin root."
echo "Checked:"
echo " - ${CLAUDE_PLUGIN_ROOT:-<unset CLAUDE_PLUGIN_ROOT>}"
echo " - $HOME/.understand-anything-plugin"
echo " - ${SELF_RELATIVE:-<unresolved path derived from ~/.agents/skills/understand-domain>}"
echo " - ${COPILOT_SELF_RELATIVE:-<unresolved path derived from ~/.copilot/skills/understand-domain>}"
echo " - $HOME/.codex/understand-anything/understand-anything-plugin"
echo " - $HOME/.opencode/understand-anything/understand-anything-plugin"
echo " - $HOME/.pi/understand-anything/understand-anything-plugin"
echo " - $HOME/understand-anything/understand-anything-plugin"
echo "Make sure the plugin is installed correctly."
exit 1
fi
Utilise $PLUGIN_ROOT pour chaque référence aux définitions d'agents dans les phases suivantes.
Phase 1 : Détecter le graphe existant
- Vérifie si
$UA_DIR/knowledge-graph.jsonexiste - S'il existe ET que
--fullN'A PAS été passé, vérifie la fraîcheur avant d'en dériver :- Lis
project.gitCommitHashdepuis les métadonnées du graphe commeGRAPH_COMMIT_RAW. Bascule vers$PROJECT_ROOT, résous-le comme un commit avant de l'utiliser dans n'importe quel diff Git, compare le commit résolu avecgit rev-parse HEAD, et inspecte les changements commités et de l'arborescence de travail au niveau du projet :GRAPH_COMMIT=$(git rev-parse --verify --end-of-options "${GRAPH_COMMIT_RAW}^{commit}" 2>/dev/null) git rev-parse HEAD git diff --name-only "$GRAPH_COMMIT" HEAD -- . git diff --cached --name-only -- . git diff --name-only -- . git ls-files --others --exclude-standard -- . - Le pathspec
-- .est requis : les commits qui touchent uniquement un projet monorepo frère ne doivent pas rendre ce graphe obsolète. Une différence de hash seule n'est pas obsolète quand le diff du projet est vide. - Ignore le répertoire de données sélectionné (
.ua/ou legacy.understand-anything/) dans la sortie de chaque commande car il contient des artefacts de graphe générés, pas une dérive de source du projet. - Si le diff commité ou n'importe quelle commande de l'arborescence de travail signale des fichiers du projet, avertis que l'extraction de domaine peut omettre ces changements. Suggère : Exécute
/understandpour actualiser le graphe de connaissances. - Exécute le diff de commit uniquement quand
GRAPH_COMMIT_RAWse résout avec succès. Si le commit du graphe ou les métadonnées Git sont manquants, invalides ou indisponibles, donne un bref avertissement de meilleure tentative et continue plutôt que de bloquer.
- Lis
- Après ce vérification préalable, procède à la Phase 3 (dériver du graphe).
- Sinon, procède à la Phase 2 (analyse légère). Quand
--fullest utilisé, saute cette vérification préalable car la commande effectue une nouvelle analyse plutôt que de consommer le graphe existant.
Phase 2 : Analyse légère (Voie 1)
Le script de prétraitement ne produit PAS un graphe de domaine — il produit la matière première (arborescence de fichiers, points d'entrée, exportations/importations) afin que l'agent domain-analyzer se concentre sur l'analyse de domaine réelle au lieu de dépenser des dizaines d'appels d'outils à explorer la base de code. Considère-le comme une fiche de triche : prétraitement Python bon marché → LLM obtient une entrée nette et petite → meilleurs résultats pour moins de coûts.
- Exécute le script de prétraitement fourni avec cette skill, en passant
$PROJECT_ROOTde la Phase 0 :python ./extract-domain-context.py "$PROJECT_ROOT"Ceci produit
$UA_DIR/intermediate/domain-context.jsoncontenant :- Arborescence de fichiers (respectant
.gitignore) - Points d'entrée détectés (routes HTTP, commandes CLI, gestionnaires d'événements, jobs cron, gestionnaires exportés)
- Signatures de fichier (exportations, importations par fichier)
- Extraits de code pour chaque point d'entrée (signature + premières lignes)
- Métadonnées du projet (package.json, README, etc.)
- Arborescence de fichiers (respectant
- Lis le fichier
domain-context.jsongénéré comme contexte pour la Phase 4 - Procède à la Phase 4
Phase 3 : Dériver du graphe existant (Voie 2)
- Lis
$UA_DIR/knowledge-graph.json - Formate les données du graphe comme contexte structuré :
- Tous les nœuds avec leurs types, noms, résumés et tags
- Toutes les arêtes avec leurs types (en particulier
calls,imports,contains) - Tous les niveaux avec leurs descriptions
- Étapes de la visite si disponibles
- C'est le contexte pour l'analyseur de domaine — aucune lecture de fichier nécessaire
- Procède à la Phase 4
Phase 4 : Analyse de domaine
- Lis le prompt de l'agent domain-analyzer depuis
$PLUGIN_ROOT/agents/domain-analyzer.md - Dispatche un sous-agent avec le prompt domain-analyzer + le contexte de la Phase 2 ou 3
- L'agent écrit sa sortie vers
$UA_DIR/intermediate/domain-analysis.json
Phase 5 : Valider et sauvegarder
- Lis la sortie de l'analyse de domaine
- Valide en utilisant le pipeline de validation de graphe standard (le schéma supporte maintenant les types domaine/flux/étape)
- Si la validation échoue, enregistre les avertissements mais sauvegarde ce qui est valide (tolérance d'erreur)
- Sauvegarde vers
$UA_DIR/domain-graph.json - Nettoie
$UA_DIR/intermediate/domain-analysis.jsonet$UA_DIR/intermediate/domain-context.json
Phase 6 : Lancer le tableau de bord
- Déclenche automatiquement
/understand-dashboardpour visualiser le graphe de domaine - Le tableau de bord détectera
domain-graph.jsonet affichera la vue de domaine par défaut