Esquisser la structure de dossiers du SDK sur papier
Une base de code construite par des agents se transforme soit en bouillie en trois mois, soit reste cohérente pendant des années - et la différence se joue avant qu'une seule ligne ne soit écrite. RakuAI a dessiné les cases en premier pour que les agents atterrissent toujours au bon endroit.
Il existe un type de travail de conception invisible de l’extérieur et porteur de l’intérieur. La structure de dossiers d’une base de code en fait partie. Cela ressemble à de la gestion de fichiers. C’est en réalité l’organigramme du code. Bien la définir tôt, et chaque PR des deux prochaines années atterrit au bon endroit. Mal la définir tôt, et chaque PR des deux prochaines années doit se disputer sur où elle appartient.
Ce samedi a été consacré à bien la définir tôt.
Ce que la structure doit supporter
Avant de dessiner des cases, j’ai fait une liste des contraintes que la structure doit satisfaire.
Chaque démo a sa propre maison. Les huit démos que j’ai spécifiées le mois dernier ont chacune besoin d’un dossier où leur code, leurs assets et leur documentation vivent ensemble. Un développeur lisant n’importe laquelle des démos ne devrait pas avoir à sauter entre quatre parties différentes du SDK pour la comprendre.
Les modules partagés sont séparables des démos. Tout ce qui est réutilisé à travers les démos (rendu HUD, saisie gestuelle, suivi du regard, synchro multijoueur, contrôle vocal, effets visuels) vit dans son propre emplacement et est consommé par les démos à travers une surface publique.
Les assets sont organisés par type, pas par démo. Un PNG de barre de vie est un widget HUD, pas un asset de la démo Arena. Les assets visuels réutilisables vivent dans un dossier d’assets partagé et les démos qui en ont besoin y font des liens.
La documentation est co-localisée avec ce qu’elle décrit. La doc d’installation du SDK vit à côté du SDK. Le guide des démos vit à côté des démos. La doc API du HUD vit à côté du module HUD. La découvrabilité de la documentation dépend surtout de son emplacement.
La config est sa propre préoccupation. Les fichiers de configuration du HUD, les layouts par défaut, les configurations de rôles multijoueur. Ce ne sont ni du code, ni des assets, ni de la documentation. Ils ont leur propre maison.
La structure
Après une matinée de tableau blanc, la disposition ressemble à ceci.
Le dossier racine est le SDK lui-même. Sous la racine :
/apps/ est l’endroit où vivent les démos. Chaque démo a son propre sous-dossier. arena_demo/ pour l’arène solo. coach_demo/ pour le coaching AR. hud_designer/ pour le concepteur de superposition HUD. streamer_demo/ pour le mode streamer. pos_demo/ pour la superposition point de vente. companion_demo/ pour le HUD compagnon AR. aimlab_demo/ pour l’entraîneur de visée AR. hudsync_demo/ pour la synchro HUD multijoueur. Chaque dossier de démo contient son propre source, sa propre configuration, ses propres assets spécifiques à la démo, et son propre README.
/modules/ est l’endroit où vit le code partagé. Six modules au départ. Le moteur de rendu HUD, que chaque démo consomme. La détection de saisie gestuelle, que la plupart des démos consomment. Le suivi du regard, utilisé par les démos qui en ont besoin. La synchro multijoueur, utilisée par les démos multijoueur en LAN. L’animateur de superposition pour les effets visuels. L’interface de contrôle vocal pour les démos qui prennent une entrée vocale. Chaque module expose une petite surface publique stable à laquelle les démos font des liens.
/assets/ est la bibliothèque d’assets partagée. Widgets HUD (barres de vie, compteurs de munitions, superpositions de boussole) en PNG et SVG. Effets audio pour les impacts, les alertes, les voix off. Icônes de geste qui montrent à l’utilisateur qu’un geste a été détecté. Les démos font des liens vers les assets ici plutôt que de les dupliquer.
/docs/ est la maison de la documentation. Un README qui présente le SDK et parcourt l’installation. Un guide des démos qui explique comment lancer chacune des huit démos. Une référence API pour le module HUD. Une référence API pour le module de contrôle vocal. La documentation est délibérément co-localisée pour qu’un développeur qui veut savoir comment fonctionne le HUD puisse lire le source et la doc dans le même dossier.
/config/ est la configuration. Le layout HUD par défaut utilisé comme point de départ pour les nouveaux projets. Des layouts d’exemple exportés depuis le concepteur de HUD. Les définitions de rôles multijoueur. Garder la config séparée du code garde les démos propres et permet à un développeur de changer un comportement sans recompiler.
Les stubs
Une structure de dossiers à elle seule n’est qu’un système de fichiers vide. L’autre chose que j’ai ébauchée aujourd’hui est un ensemble de stubs de code qui montrent aux agents (quand ils commenceront finalement à écrire du code sur cette structure) à quoi devrait ressembler une implémentation réelle à chaque point d’entrée.
Les stubs sont en pseudocode Python pour l’instant. Ils seront traduits vers le langage de production (C++ pour le runtime, avec des liaisons vers Python et d’autres écosystèmes) une fois le dépôt du moteur ouvert. La forme Python est ce qui me permet de raisonner sur les interfaces sans me perdre dans les détails d’implémentation.
Un stub d’exemple, pour le module de saisie gestuelle. Approximativement :
def detect_gesture(frame):
"""Detect gestures like swipe, point, raise, duck in a single sensor frame."""
if is_swipe(frame):
return "swipe"
elif is_raise(frame):
return "raise_arm"
else:
return None
Ce n’est pas le code de production. C’est le contrat. Le code de production remplacera is_swipe et is_raise par de vrais pipelines de vision par ordinateur. L’interface reste la même. La signature est ce sur quoi les démos coderont. Verrouiller la signature tôt signifie que je peux livrer les démos avant que le pipeline de vision par ordinateur ne soit blindé, parce que les démos ne dépendent pas de l’implémentation, elles dépendent de l’interface.
J’ai ébauché des stubs de cette forme pour chaque module du dossier /modules/. Six petits fichiers Python. Aucun d’entre eux n’implémente quoi que ce soit. Tous définissent le contrat que les implémentations éventuelles devront honorer.
Pourquoi les agents en ont besoin
C’est la connexion avec l’effectif d’agents d’il y a quelques samedis.
Quand viendra le moment d’écrire le vrai code, les agents n’inventeront pas l’architecture. L’architecture est sur papier. La structure de dossiers leur dit où va le nouveau code. Les stubs de module leur disent quelle interface implémenter. L’organisation des assets leur dit où chercher les choses dont ils ont besoin. La structure de la documentation leur dit où mettre la documentation qu’ils écrivent.
C’est la différence entre une base de code construite par des agents qui se transforme en bouillie après trois mois et une qui reste cohérente pendant des années. La structure est la discipline. Les agents héritent de la discipline à travers la structure.
Sans ce travail préparatoire, un agent à qui on demanderait « implémenter la saisie gestuelle » inventerait un dossier, inventerait une API, écrirait le code, et produirait quelque chose qui fonctionnerait isolément. Multiplié sur six modules, cette approche produit six mini-moteurs incompatibles. La structure prévient ce mode de défaillance en dessinant les cases dans lesquelles les agents doivent écrire.
Ce qui est difficile là-dedans
Quelques éléments honnêtes.
Les structures de dossiers veulent grandir. Dans six mois je voudrai ajouter un septième module. La structure doit permettre cela sans devenir un tiroir fourre-tout. La règle que je m’impose : tout nouveau dossier de premier niveau doit justifier pourquoi il n’est pas un sous-dossier d’un dossier existant. La plupart des nouvelles choses s’avèrent être des sous-dossiers.
Les stubs ont besoin de maintenance. À mesure que les vraies implémentations arrivent, les stubs deviennent obsolètes. Les agents qui lisent les stubs comme « le contrat » hériteront de toute dérive entre le stub et l’implémentation réelle. La solution est de faire des stubs la source de vérité, et d’exiger que les implémentations réelles les mettent à jour quand le contrat change.
Certains de ces dossiers sont spéculatifs. Le dossier /config/ est un pari que les fichiers de configuration du runtime seront une véritable catégorie d’artefact dans ce SDK. S’il s’avère que ce n’est pas le cas, le dossier rétrécit ou fusionne avec autre chose. Je suis à l’aise avec ça. Il est moins coûteux de retirer un dossier plus tard que d’en inventer un dans un an quand la convention aura déjà dérivé.
La suite
Le samedi prochain, c’est la conception de la surface API. Chacun des six modules ci-dessus a besoin de voir sa surface publique spécifiée. Cela signifie décider quels types de données traversent la frontière, quels codes d’erreur sont renvoyés, quels événements sont émis. Avec la structure de dossiers faite, la conception d’API a un endroit où atterrir.
Après cela vient la spécification démo par démo de quels modules chaque démo consomme et dans quel ordre. Puis l’architecture du runtime. Puis, enfin, le dépôt du moteur s’ouvre.
Le portefeuille de brevets attend depuis une décennie. Quelques semaines de plus de travail de conception pour bien l’ancrer ne seront pas ce qui nous coûtera la fenêtre.
Structure de dossiers terminée. La base de code a maintenant une forme, même s’il n’y a pas encore de code dedans.
Un SDK qui ne bougera pas sous vos pieds
Une structure de dossiers qui ne changera pas, une surface API verrouillée avant l'implémentation - construisez sur un runtime spatial conçu pour durer.