Aller au contenu
GL
Tous les posts

#Agents IA#Architecture

Parts : une fondation que les agents peuvent assembler

Pourquoi je garde un catalogue de stack, de gates stricts et de modules plutôt qu'un template, et comment un agent l'importe.

Chaque nouveau projet que je démarre répète les mêmes décisions : framework, auth, règles de lint, structure des dossiers, billing. Avant, je copiais un vieux repo et je supprimais des affaires. Maintenant je garde un catalogue à la place. Ça s'appelle Parts, et c'est fait pour être lu par des agents.

Un catalogue, pas un template

Un template, c'est une app finie que tu clones et que tu dois ensuite dégraisser. Tu hérites de tout, même de ce dont tu n'as pas besoin, et l'app que tu as clonée continue de dériver de celle que tu construis.

Parts n'est pas une application qui roule. C'est une source de conventions et de blocs de construction. Dans un nouveau repo, je dis à un agent quelles parts apporter. L'agent les copie, les adapte au projet et les branche.

La base reste petite. Chaque capacité optionnelle est un module avec un point d'entrée clair, ses propres dépendances et son README. Aujourd'hui, ça couvre Better Auth, des outils de catalogue Stripe, une locale française optionnelle, un shell desktop Tauri 2, et deux cibles d'hébergement (Vercel et Cloudflare Workers).

Des gates qui ne plient pas

Les agents écrivent beaucoup de code vite. Sans limites, le code devient vite mélangé aussi. La base vient avec des vérifications strictes qui font planter le build.

  • Oxlint plus ESLint au complet, zéro warning, aucune suppression inline.
  • TypeScript strict et diagnostics Effect.
  • Knip pour le code mort.
  • Complexité cyclomatique plafonnée à 6.
  • Un fichier écrit à la main ne peut pas dépasser 1 000 lignes.
  • Un dossier ne peut pas contenir plus de 8 fichiers de code écrits à la main.

Les deux dernières sont celles qui changent la façon de travailler d'un agent. Quand un fichier atteint le plafond, l'agent doit le découper par responsabilité. Quand un dossier est plein, il doit regrouper les fichiers par préoccupation. Le code généré est exclu. Le gate au complet roule en un seul script :

"check": "bun run lint && bun run typecheck && bun run knip"

Les limites sont dures exprès. Un plafond de 6 veut dire que les fonctions restent petites et que les branches se déplacent dans des morceaux nommés. Je préfère que l'agent découpe une fonction plutôt qu'il argumente avec moi pour savoir pourquoi il ne l'a pas fait.

Des frontières de service remplaçables

Le starter est une app de todos, mais ce qui est utile, c'est la façon dont elle est câblée. Les dépendances de session, de tâche, de compte et de billing sont des Effect Layers. Le code des features appelle un service comme TodoService ou BillingService. Il n'appelle jamais Better Auth ou Convex directement.

Ça veut dire qu'une destination peut changer de provider à une seule frontière. Le provider de billing dans le starter retourne un reçu mock déterministe et ne fait aucun appel de paiement externe. Remplace cette seule layer par un vrai adapter Stripe et les appelants ne changent pas. Le même seam permet à un test de fournir une session déconnectée sans toucher au service d'accès.

Les règles du serveur restent sur le serveur. Le module de rôles et permissions met les vérifications d'identité et d'autorité dans des builders Convex partagés, donc cacher un bouton n'est jamais le seul cadenas.

Comment un agent importe une part

Le README commence par un prompt que je colle dans n'importe quel coding agent. Il pointe vers le repo et demande à l'agent de lire README.md, AGENTS.md et instructions/start-project.md. Ensuite il fixe les règles de la job :

  • Me demander le nom du projet, la destination et les parts que je veux.
  • Expliquer les compromis et confirmer mes choix avant de changer des fichiers.
  • Mettre en place la base et les parts convenues, puis vérifier le résultat.
  • Ne pas faire de commit, de push ni de deploy à moins que je le dise.

Le guide start-project m'interroge sur le billing, les langues, les cibles natives et l'hébergement. Ensuite il crée un nouveau projet ou fusionne les parts choisies dans un projet existant, sans remplacer le stack qui est déjà là.

Le README de chaque module dit ce qu'il fournit, quels fichiers importer, quoi configurer et comment vérifier le résultat. Importer, ça veut aussi dire connecter. Si un agent apporte les rôles et permissions, il applique aussi les builders partagés aux fonctions backend protégées. S'il apporte le login pour agents, il se connecte et exerce les flows d'admin.

Être honnête sur le statut

Parts indique ce qui est réel. Certaines pièces sont des templates implémentés. Certaines sont des références d'intégration adaptées de mes autres projets, et certaines sont encore planifiées. Un adapter WorkOS et un module OpenRouter sont sur la liste des choses planifiées. On dit à l'agent de rapporter lequel est lequel et de vérifier le comportement importé dans la destination avant de déclarer quoi que ce soit terminé.

Cette honnêteté fait partie du design. Une fondation en laquelle tu ne peux pas avoir confiance est pire que pas de fondation.

Pourquoi ça marche pour moi

Démarrer un projet, c'est maintenant une conversation et une checklist, pas une journée de setup. Le niveau de qualité est le même au projet cinq qu'au projet un, parce que les gates voyagent avec les parts. Et quand j'améliore une part, tous les projets futurs profitent de l'amélioration.