Déclencheurs
- language server protocol
- intégration LSP
- code intelligence
- indexation sémantique
- symbol graph
- navigation de code
- go to definition
- find references
- documentation au survol
- graph daemon
- LSP multi-langage
- LSIF
- visualisation de code
- résolution de symboles
- orchestration LSP
Instructions
Construire l'agrégateur LSP
- Orchestrer plusieurs clients LSP (TypeScript, PHP, Go, Rust, Python) de manière concurrente.
- Transformer les réponses LSP en schéma de graphe unifié (nœuds : fichiers/symboles, arêtes : contains/imports/calls/refs).
- Implémenter les mises à jour incrémentielles en temps réel via des observateurs de fichiers et des hooks git.
- Maintenir des temps de réponse inférieurs à 500 ms pour les requêtes definition/reference/hover.
- La prise en charge TypeScript et PHP doit être prête pour la production en premier.
Créer une infrastructure d'index sémantique
- Construire nav.index.jsonl avec les définitions de symboles, les références et la documentation au survol.
- Implémenter l'import/export LSIF pour les données sémantiques pré-calculées.
- Concevoir une couche de cache SQLite/JSON pour la persistance et le démarrage rapide.
- Diffuser les diffs de graphe via WebSocket pour les mises à jour en direct.
- Assurer les mises à jour atomiques qui ne laissent jamais le graphe dans un état incohérent.
Optimiser pour l'échelle et les performances
- Gérer 25 000+ symboles sans dégradation (cible : 100 000 symboles à 60 fps).
- Implémenter des stratégies de chargement progressif et d'évaluation paresseuse.
- Utiliser les fichiers mappés en mémoire et les techniques zero-copy si possible.
- Regrouper les requêtes LSP pour minimiser la surcharge d'aller-retour.
- Mettre en cache agressivement mais invalider précisément.
Conformité du protocole LSP
- Suivre strictement la spécification LSP 3.17 pour toutes les communications client.
- Gérer correctement la négociation des capacités pour chaque serveur de langage.
- Implémenter la gestion appropriée du cycle de vie (initialize → initialized → shutdown → exit).
- Ne jamais supposer les capacités ; toujours vérifier la réponse des capacités du serveur.
Exigences de cohérence du graphe
- Chaque symbole doit avoir exactement un nœud de définition.
- Toutes les arêtes doivent référencer des ID de nœud valides.
- Les nœuds de fichier doivent exister avant les nœuds de symbole qu'ils contiennent.
- Les arêtes d'importation doivent se résoudre en nœuds de fichier/module réels.
- Les arêtes de référence doivent pointer vers les nœuds de définition.
Contrats de performance
- Le point de terminaison /graph doit retourner en moins de 100 ms pour les datasets de moins de 10 000 nœuds.
- Les recherches /nav/:symId doivent s'accomplir en moins de 20 ms (en cache) ou 60 ms (non en cache).
- Les flux d'événements WebSocket doivent maintenir une latence inférieure à 50 ms.
- L'utilisation de mémoire doit rester sous 500 MB pour les projets typiques.
Flux de travail
- Configurer l'infrastructure LSP : installer les serveurs de langage, vérifier qu'ils fonctionnent.
- Construire le graph daemon avec serveur WebSocket, points de terminaison HTTP, observateur de fichiers.
- Intégrer les serveurs de langage avec les capacités appropriées, support multi-root workspace, regroupement de requêtes.
- Optimiser les performances : profiler les goulots d'étranglement, implémenter le diffing de graphe, utiliser les worker threads, ajouter la mise en cache distribuée.
Livrables
Architecture centrale de graphd
interface GraphDaemon {
lspClients: Map<string, LanguageClient>;
graph: {
nodes: Map<NodeId, GraphNode>;
edges: Map<EdgeId, GraphEdge>;
index: SymbolIndex;
};
httpServer: {
'/graph': () => GraphResponse;
'/nav/:symId': (symId: string) => NavigationResponse;
'/stats': () => SystemStats;
};
wsServer: {
onConnection: (client: WSClient) => void;
emitDiff: (diff: GraphDiff) => void;
};
}
interface GraphNode {
id: string;
kind: 'file' | 'module' | 'class' | 'function' | 'variable' | 'type';
file?: string;
range?: Range;
detail?: string;
}
interface GraphEdge {
id: string;
source: string;
target: string;
type: 'contains' | 'imports' | 'extends' | 'implements' | 'calls' | 'references';
weight?: number;
}
Format d'index de navigation
{"symId":"sym:AppController","def":{"uri":"file:///src/controllers/app.php","l":10,"c":6}}
{"symId":"sym:AppController","refs":[{"uri":"file:///src/routes.php","l":5,"c":10}]}
{"symId":"sym:AppController","hover":{"contents":{"kind":"markdown","value":"```php\nclass AppController extends BaseController\n```"}}}
Métriques de succès
- graphd fournit une code intelligence unifiée dans tous les langages
- Go-to-definition s'exécute en moins de 150 ms pour n'importe quel symbole
- La documentation au survol apparaît en moins de 60 ms
- Les mises à jour du graphe se propagent aux clients en moins de 500 ms après l'enregistrement du fichier
- Le système gère 100 000+ symboles sans dégradation des performances
- Zéro incohérence entre l'état du graphe et le système de fichiers
Vérifier
- La cause racine est énoncée en une phrase et est soutenue par un artefact concret (stack trace, ligne de log, diff, sortie de profiler)
- Le reproducer est minimal et s'exécute localement ; la commande exacte et la sortie observée sont capturées
- La correction a été vérifiée en réexécutant le reproducer et en montrant que la sortie précédemment défaillante passe maintenant
- Un test de régression (ou une surveillance/alerte) a été ajouté pour que le même bug soit attrapé automatiquement la prochaine fois
- Les chemins de code adjacents qui partagent le même mode de défaillance ont été vérifiés, pas seulement le symptôme rapporté
- Si la correction affecte la sécurité, les performances ou l'intégrité des données, le compromis est nommé et quantifié