Ce que je fais
Je guide l'orchestrateur pour créer de nouvelles fonctionnalités (ne pas modifier l'existant) avec une analyse préalable de réutilisation, de configuration et de compatibilité. Contrairement aux refactorisations, il n'y a aucun code préexistant à préserver : la conception part des besoins de l'utilisateur.
Quand utiliser ce skill (plutôt que refactor-protocol) :
- L'utilisateur demande un endpoint, un service, un job, un handler, un événement ou une configuration qui N'existe PAS
- La tâche est une création pure, pas une modification de comportement existant
- Le résultat ajoute des fichiers au dépôt, il ne change pas la signature des fichiers existants
Quand NE PAS utiliser ce skill (utiliser refactor-protocol à la place) :
- Modifier la signature d'un service existant
- Changer le comportement d'un endpoint qui existe déjà
- Renommer, extraire ou déplacer du code
PHASE 0 — Validation de la structure (toujours en premier)
- Charger le skill
project-structureet exécuter la validation complète - Détecter le type d'hôte :
FUNCTIONS|WEBAPP|NUGET_LIBRARY - Agir selon le résultat :
| État | Action |
|---|---|
HARD_BLOCK | Arrêter. Informer l'utilisateur. |
NUGET_LIBRARY | Créer un endpoint HTTP est inattendu. Demander : "Voulez-vous ajouter une opération publique à la bibliothèque ou y a-t-il vraiment un hôte que je n'ai pas détecté ?" |
PREGUNTA | Résoudre les questions avant de continuer |
OK / WARNING | Continuer à la PHASE 1 |
PHASE 1 — Recueil des exigences
L'orchestrateur déduit ce qu'il peut de la description de l'utilisateur ($ARGUMENTS) et ne pose que les questions qui ne sont pas claires. Ne pas poser de questions dont la réponse est déjà dans la description.
1.1 Nom, objectif et type de fonctionnalité
- Endpoint HTTP (Function/Controller) :
[VERBE] /route — description - Service métier : nom du service et responsabilité
- Job/Event handler : trigger + action
- Option de configuration : nom de l'option et son objectif
1.2 Classification READ vs MUTATION
Déterminer si la fonctionnalité mute l'état ou est en lecture seule. Cela affecte :
- Où vont les DTOs de réponse
- Si une transaction / idempotence est requise
- Quels tests sont nécessaires
| Type | Caractéristiques | Implication |
|---|---|---|
| READ-ONLY | GET, renvoie des données existantes, n'écrit pas | DTOs éphémères, tests minimaux |
| MUTATION | POST/PUT/DELETE, écrit ou change l'état | Nécessite des tests de succès + erreur |
1.3 Recueil des entrées/sorties attendues
- Requête : structure du corps ou des paramètres de requête
- Réponse : structure du corps de réponse, codes de statut
- Erreurs : quelles erreurs mapper à quels codes de statut
PHASE 1.5 — Analyse de réutilisation (CRITIQUE, ne pas sauter)
Objectif : détecter si la fonctionnalité existe déjà partiellement ou totalement avant de créer quoi que ce soit.
Étapes
- Rechercher des services existants dans
*.Impl/avec@exploreen utilisant le domaine de la fonctionnalité - Rechercher des méthodes candidates qui couvrent 80%+ du comportement requis :
- Existe-t-il une méthode qui renvoie déjà la donnée nécessaire avec un filtre trivial ?
- Existe-t-il une méthode qui pourrait être surchargée pour ajouter le cas ?
- Rechercher des endpoints similaires dans
*.API/avec la même forme de requête/réponse
Arbre de décision
Existe-t-il une méthode qui couvre 100% du cas ?
└── OUI → NE PAS créer de nouvelle méthode. Créer uniquement :
· Endpoint (Function/Controller) dans *.API/
· DTO Request/Response exclusif dans *.API/
· Test de la forme de la réponse
Existe-t-il une méthode quasi-idéale (filtre, pagination, ordre) ?
├── OUI → envisager :
│ ├── Ajouter un paramètre optionnel à la méthode existante (avec valeur par défaut)
│ ├── Créer une surcharge avec une signature plus spécifique
│ └── Créer une méthode d'extension qui enveloppe l'existante
└── NON → continuer avec la création d'une nouvelle méthode
Existe-t-il un service connexe mais différent (ex. responsabilité similaire) ?
├── OUI → demander à l'utilisateur : "Est-ce que j'étends [CSXxxService] ou j'en crée un nouveau [CSYyyService] ?"
└── NON → créer un nouveau service
Résultat attendu de cette phase
Une de ces trois décisions, présentée à l'utilisateur avant de continuer :
- Réutilisation pure : la fonctionnalité est implémentée comme un wrapper d'une méthode existante
- Extension : ajouter une surcharge/méthode à un service existant
- Création nouvelle : nouveau service et nouvelles méthodes (justifier pourquoi la réutilisation n'est pas possible)
PHASE 1.6 — Analyse de configuration (NOUVELLE)
Objectif : détecter si la fonctionnalité nécessite des paramètres configurables et, si oui, où les définir.
Questions clés
- La fonctionnalité a-t-elle des valeurs par défaut raisonnables sans configuration externe ?
- Y a-t-il des seuils, pagination, timeouts, ou indicateurs qui devraient être configurables par environnement ?
- Se connecte-t-elle à un système externe avec URL/clé/secret ?
- Nécessite-t-elle des feature flags pour un déploiement progressif ?
Arbre de décision
La fonctionnalité nécessite-t-elle une configuration ?
├── NON → ne pas créer IXxxOptions, ne pas toucher à AddCustomConfiguration
└── OUI → continuer
Quel type de configuration ?
├── Chaîne de connexion ou secret
│ └── Utiliser IConfiguration avec un nom dans appsettings.json (géré par AddCustomConfiguration)
├── Valeur simple (seuil, timeout, indicateur)
│ └── Créer IXxxOptions dans *.Impl/ (interface) + ajouter à AddCustomConfiguration<T>("clé")
└── Liste de valeurs (origines autorisées, mappings)
└── Créer IXxxOptions avec une propriété de type IEnumerable<T>
Convention du projet
Le projet utilise AddCustomConfiguration<IXxxOptions>("section-config") dans IoCExtensions.cs
(lignes 43-45 du projet actuel). Les interfaces vivent dans *.Impl/ et sont référencées depuis
*.Impl/Services/.
Résultat attendu
Si la fonctionnalité nécessite une configuration, présenter à l'utilisateur :
- Nom de l'interface (ex.
IPendingPaymentOptions) - Propriétés avec leurs types et valeurs par défaut
- Section dans
appsettings.json(ex."RAMBLA.PendingPayment") - Modification de
IoCExtensions.AddCSLevelBooking()
Si NON, l'indiquer explicitement dans le plan.
PHASE 1.7 — Analyse de l'impact sur l'API publique
Objectif : éviter de casser les consommateurs existants.
Si la fonctionnalité réutilise une méthode existante
- La méthode est-elle conservée avec la même signature ? → sans impact
- Ajoute-t-on un paramètre optionnel ? → vérifier qu'aucun site d'appel n'est cassé
- Ajoute-t-on une surcharge ? → vérifier que le compilateur résout sans ambiguïté
- Renomme-t-on ? → rechercher tous les sites d'appel avec
grepet migrer
Si la fonctionnalité ajoute un nouveau service
- Le service est-il enregistré dans DI ? → assurer l'enregistrement dans
IoCExtensions - Un service existant a-t-il une dépendance circulaire potentielle ? → vérifier
Si la fonctionnalité ajoute un nouvel endpoint
- La route entre-t-elle en collision avec une autre route existante ? → vérifier
- La méthode HTTP est-elle cohérente avec REST ? (GET pour la lecture, POST pour la mutation)
PHASE 1.8 — PREFLIGHT des tests de régression (obligatoire)
Objectif : avant de générer du nouveau code ou de modifier l'existant, vérifier que les composants qui vont être touchés (même tangentiellement) ont une couverture de tests. Si ce n'est pas le cas, les créer et les exécuter avant de commencer l'implémentation.
Étapes
-
Identifier la surface tangentielle : à partir de la PHASE 1.5 (réutilisation vs extension vs nouveau), lister :
- Services existants dont les méthodes vont être étendues ou surchargées
- Interfaces existantes qui vont être modifiées
- Endpoints existants qui peuvent être affectés par le routage/DI
- Tout fichier existant qui va être édité (pas créé)
-
Pour chaque composant existant qui va être touché :
- Rechercher des tests dans
src/*.Test*/**qui l'exercent - S'il a une couverture → OK, continuer
- Si aucune couverture → HARD BLOCK :
- Invoquer
@refactor-worker-testspour créer des tests de caractérisation du comportement actuel - Invoquer
@refactor-verifierpour confirmer qu'ils passent au vert - Commit séparé :
test(characterization): add characterization tests for <classes>
- Invoquer
- Rechercher des tests dans
-
Si la fonctionnalité est 100% création nouvelle (ne touche aucun fichier existant) :
- Pas de surface de régression → omettre PREFLIGHT
- Mais les tests de la nouvelle fonctionnalité sont créés en PHASE 4 et doivent passer en PHASE 5
Critère de clôture (PHASE 5)
Pour valider la fonctionnalité, @refactor-verifier doit confirmer que passent :
- Nouveaux tests de la fonctionnalité (service + endpoint)
- Tests existants des composants tangentiels (régression)
Si l'un ou l'autre échoue, la fonctionnalité ne peut pas être clôturée.
PHASE 2 — Arbre de décision : quoi créer et où
Appliquer la décision de la PHASE 1.5 (réutilisation / extension / nouveau) plus la PHASE 1.6 (config).
Pour endpoint READ-ONLY avec réutilisation
*.API/
+ {Nom}Function.cs — Function/Controller nouveau
+ {Nom}Request.cs — exclusif à la présentation
+ {Nom}Response.cs — exclusif à la présentation
*.Test*/
+ {Nom}FunctionTests.cs — test de la forme de la réponse (PAS de logique)
Pour endpoint MUTATION avec nouveau service
*.Contracts/
+ ICS{Nom}Service.cs — interface du service
+ {Nom}Request.cs — si Request partagé
+ {Nom}Response.cs — si Response partagé
*.Impl/
+ CS{Nom}Service.cs — implémentation
+ I{Nom}Options.cs — UNIQUEMENT si la PHASE 1.6 a détecté une config
*.API/
+ {Nom}Function.cs — Function/Controller
+ {Nom}Request.cs — exclusif (si non mis dans Contracts)
+ {Nom}Response.cs — exclusif (si non mis dans Contracts)
*.Test*/
+ CS{Nom}ServiceTests.cs — happy path + au moins une erreur
Pour extension d'un service existant
*.Contracts/
~ ICS{Nom}Service.cs — ajouter la signature de la méthode (ou créer une surcharge)
*.Impl/
~ CS{Nom}Service.cs — implémenter la nouvelle méthode/surcharge
*.API/
+ {Nom}Function.cs — Function/Controller nouveau
+ {Nom}Request.cs — si exclusif
+ {Nom}Response.cs — si exclusif
*.Test*/
+ (ou ~) tests du service — ajouter un cas pour la nouvelle méthode
PHASE 3 — Plan de création
Avant d'invoquer les workers, l'orchestrateur présente ce plan à l'utilisateur et attend une confirmation explicite :
[PLAN DE CRÉATION] Fonctionnalité : <nom> — <description brève>
Hôte : <FUNCTIONS | WEBAPP>
Classification : <READ-ONLY | MUTATION>
Stratégie : <RÉUTILISATION | EXTENSION | NOUVEAU>
Analyse de réutilisation (PHASE 1.5) :
· Service candidat : <ICSXxxService> ou "aucun"
· Méthode candidate : <XxxService.YyyMethod> ou "aucun"
· Décision : <RÉUTILISATION | EXTENSION | NOUVEAU>
Analyse de configuration (PHASE 1.6) :
· Nécessite config : <OUI | NON>
· Si oui : <IXxxOptions + section appsettings>
Impact sur l'API publique (PHASE 1.7) :
· Sites d'appel affectés : <liste> ou "aucun"
· Breaking change : <OUI | NON>
Artefacts à créer :
*.Contracts/ ([N] fichiers) :
+ ICS{Nom}Service.cs — nouvelle interface (ou : ajouter une méthode à IXxx)
+ {Nom}Request.cs — si type partagé
+ {Nom}Response.cs — si type partagé
*.Impl/ ([N] fichiers) :
+ CS{Nom}Service.cs — implémentation du service
+ I{Nom}Options.cs — UNIQUEMENT si nécessite config (PHASE 1.6)
*.API/ ([N] fichiers) :
+ {Nom}Function.cs — Azure Function (ou : {Nom}Controller.cs)
+ {Nom}Request.cs — si type exclusif
+ {Nom}Response.cs — si type exclusif
*.Test*/ ([N] fichiers) :
+ CS{Nom}ServiceTests.cs — tests du service (happy path + erreur)
+ {Nom}FunctionTests.cs — tests de l'endpoint (si applicable)
Modifications aux fichiers existants :
~ src/.../IoCExtensions.cs — enregistrer le service et les options (si applicable)
Ordre d'exécution : Contracts → Impl → Présentation → Tests
Dois-je procéder ?
Sans approbation explicite de l'utilisateur, n'invoquer aucun worker.
PHASE 4 — Exécution
Ordre des workers
@refactor-worker-contracts— seulement s'il y a de nouveaux types ou signatures dans*.Contracts/@refactor-worker-impl— chaque fois qu'il y a du code dans*.Impl/@refactor-worker-presentation— chaque fois qu'il y a un endpoint@refactor-worker-tests— toujours à la fin
Remarque : N'invoquez PAS
@refactor-worker-crosscuttingsauf si la fonctionnalité expose une nouvelle Service Gateway. C'est un cas rare lors de la création ; cela arrive généralement lors de refactorisations.
Instructions à chaque worker
Inclure dans le prompt :
- Le plan complet (PHASE 3)
- Les patrons du projet : lire un fichier similaire avant de créer
- La liste exacte des fichiers avec leur contenu attendu
- Si la PHASE 1.6 a détecté une config : le chemin de
IXxxOptionset la section de configuration
PHASE 5 — Vérification et commit
- Invoquer
@refactor-verifier - Si PASS → proposer un commit avec le format :
feat(<scope>): add <nom-court> feature - Added ICS{Nom}Service interface and CS{Nom}Service implementation - Added {VERBE} /{route} Function/Controller - Added {Nom}Request/{Nom}Response contracts - Added I{Nom}Options for new configuration (si applicable) - Added unit tests for CS{Nom}Service - Si FAIL → identifier la couche défaillante, ré-invoquer le worker, re-vérifier
Patrons par hôte
FUNCTIONS — Azure Functions Isolated Worker
Avant de créer la Function, lire une Function HTTP existante et copier son style. Exemple typique :
public class {Nom}Function
{
private readonly I{Nom}Service _{champ};
public {Nom}Function(I{Nom}Service {champ}) => _{champ} = {champ};
[Function("{Nom}Function")]
public async Task<HttpResponseData> RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "{route}")] HttpRequestData req)
{
var request = await req.ReadFromJsonAsync<{Nom}Request>();
var result = await _{champ}.ExecuteAsync(request);
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(result);
return response;
}
}
Vérifier avant de créer :
AuthorizationLevel.FunctionouAuthorizationLevel.Anonymous?- Le verbe HTTP correspond-il au comportement (lecture/écriture) ?
- Les noms des paramètres respectent-ils la convention (req, request, etc.) ?
WEBAPP — ASP.NET Core Controllers
[ApiController]
[Route("api/[controller]")]
public class {Nom}Controller : ControllerBase
{
private readonly I{Nom}Service _{champ};
public {Nom}Controller(I{Nom}Service {champ}) => _{champ} = {champ};
[HttpPost("{route}")]
public async Task<ActionResult<{Nom}Response>> ExecuteAsync({Nom}Request request)
{
var result = await _{champ}.ExecuteAsync(request);
return Ok(result);
}
}
Vérifier avant de créer :
- Le routage correspond-il à la convention existante ?
- Les attributs
[FromBody],[FromQuery], etc., sont-ils présents si nécessaire ? - La méthode de retour est-elle cohérente (Ok, Created, etc.) ?
Résumé des types par couche
| Couche | Rôles | Exemples |
|---|---|---|
*.Contracts/ | Interfaces de service, DTOs partagés (Request/Response) | ICSBookingService, BookingRequest |
*.Impl/ | Implémentations de services, options de configuration | CSBookingService, IBookingOptions |
*.Impl/Services/ | Implémentations concrètes avec logique métier | CSBookingService, CSPaymentService |
*.API/ | Endpoints HTTP (Functions ou Controllers), DTOs exclusifs | GetBookingFunction, BookingRequest |
*.Test*/ | Tests unitaires et d'intégration | CSBookingServiceTests, GetBookingFunctionTests |