À propos du projet

testgraph est un sélecteur de tests au niveau des parcours (journey-level). À partir d'un diff git, il détermine quels flux orientés utilisateur un changement pourrait avoir rompus et dans quel ordre ils doivent être testés, renvoyant une courte liste classée plutôt qu'une directive de tout réexécuter. Il ne pilote pas délibérément les navigateurs, ne génère pas de tests et ne s'auto-guérit pas ; son rôle est d'agir comme la couche supérieure aux pilotes existants, à savoir décider de ce qui mérite d'être testé. Fonctionnement Un registre de parcours nomme chaque parcours utilisateur et ses symboles d'entrée, tels que des gestionnaires de routes ou un balayage de scheduler. Le module propose ébauche un registre pour un nouveau dépôt en scannant les décorateurs de route Python et les conventions Next.js par rapport à l'index, le marquant comme non approuvé (approved false) jusqu'à ce qu'un humain le lise, afin qu'un registre non approuvé s'exécute bruyamment mais jamais silencieusement. Pour un diff, testgraph mappe les plages de lignes modifiées aux symboles qui les possèdent, les graines ; parcourt le graphe d'arêtes CodeGraph en inverse, transitivement, vers chaque symbole dépendant d'une graine, l'ensemble impacté ; et rapporte les parcours dont les symboles d'entrée tombent dans cet ensemble, classés par fan-in, chacun portant la confiance du chemin d'arête le plus fort l'ayant atteint. La confiance est le maximum sur les chemins du minimum sur les arêtes, donc une chaîne n'est fiable que selon son maillon le plus faible, tandis qu'une seule route solide suffit. Un parcours atteint uniquement via des arêtes faibles ou synthétisées est signalé pour vérification manuelle plutôt que d'être silencieusement approuvé, et n'est jamais supprimé de la sélection. L'outil privilégie le rappel (recall-first) : il préfère la sur-sélection à l'omission silencieuse d'un parcours réellement affecté par un changement. Avant de répondre, un garde d'intégrité refuse de s'exécuter sur un index CodeGraph corrompu ou obsolète, car un graphe erroné produit une réponse fausse avec assurance. La résolution du registre effectue des recherches selon la règle du premier résultat gagnant : une variable d'environnement de secours, puis un répertoire .testgraph/journeys à l'intérieur du dépôt (emplacement recommandé), puis un répertoire journeys à côté du package dans le checkout du projet. Un registre est associé à sa cible auto-déclarée plutôt qu'à son nom de fichier, dans chaque emplacement, et un registre copié d'un autre projet sans modification est refusé. Prérequis et installation Python 3.11 ou plus récent utilisant uniquement la bibliothèque standard, sans dépendances tierces ; git pour l'entrée du diff ; et un dépôt cible avec un index CodeGraph produit par codegraph init. Installation via PyPI avec pip install testgraph. Le wheel ne contient que le package, tandis que le harnais de mesure et les registres de dogfooding résident dans le dépôt. CLI et MCP Les points d'entrée en ligne de commande incluent select, avec une sortie lisible par l'humain ou en JSON destinée à une passerelle CI ou un autre agent ; export, qui écrit une carte de parcours statique lue par un agent avant le commit ; propose ; record ; et un mode résumé. Le serveur MCP stdio expose deux outils, testgraph_impact et testgraph_journeys, et est enregistré par dépôt. Il utilise uniquement la stdlib et importe les modules d'analyse paresseusement, donc un serveur inactif n'a pas chargé sqlite3, ne détient aucune connexion à la base de données et ne garde aucun index en mémoire. Le README rapporte un RSS de 15,2 Mo mesuré après un handshake complet, contre 62 à 69 Mo pour un serveur MCP SDK Python typique. Câblage et registre (ledger) hooks/install.sh installe un hook pre-push dans chaque dépôt avec un registre approuvé, afin que chaque push affiche les parcours qu'il aurait pu rompre. Le hook exécute d'abord codegraph sync, car les graines proviennent de plages de lignes et un index construit avant le déplacement du code résoudrait un diff contre des plages obsolètes ; si les octets d'un fichier modifié ne correspondent toujours pas à la copie indexée, la réponse se dégrade et nomme le fichier. Le hook ne fait jamais échouer un push, chaque chemin sortant avec un code zéro, et peut être désactivé par dépôt via un paramètre git config ou supprimé avec un flag uninstall. Chaque exécution ajoute une ligne de sélection à un registre JSONL ; la commande record écrit l'autre moitié (ce que l'exécution d'un parcours a trouvé), sehingga les deux joints par dépôt et commit peuvent compter un parcours ayant échoué sur un commit dont la sélection ne l'avait pas nommé, ce qui est décrit comme une sous-sélection silencieuse. Statut L'outil est décrit comme un spike de phase 1 plus des chemins pondérés par la confiance, fonctionnel et validé sur une cible de dogfooding : rappel de 1,00 sur cinq commits étiquetés manuellement avec une précision moyenne de 0,68, et 1,00 sur vingt sites de mutation ensemencés évalués par rapport à un oracle AST indépendant, avec le garde d'intégrité testé et le schéma fixé. La portée est limitée à cette cible unique, analysant les fichiers backend et frontend avec des parcours enregistrés sur des points d'entrée backend. Le README note également que des mesures ultérieures sur deux dépôts sans registre ont infirmé la précédente revendication d'économies : avec 23 parcours, un dépôt a donné un histogramme de zéro parcours pour 38 commits et 23 pour 2 commits, et avec 207 parcours, un autre n'a évité que 54,1 % des exécutions de parcours une fois les commits ne touchant aucune surface enregistrée exclus ; ainsi, les chiffres de sélection doivent être lus comme un plancher sur le couplage plutôt que comme une promesse d'économies. La même mesure a confirmé le classement, avec une sélection complète du registre (faux positif) signalée pour vérification manuelle à une confiance de 0,3, tandis qu'un rayon d'impact important et réel est revenu propre à 0,9.