[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CSVFX50VE7WXX8C6X0XSY2":3,"skill-same:01M6CSVFX50VE7WXX8C6X0XSY2":155},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":50,"linkOnly":51,"markdownContent":52,"markdownBody":53,"frontMatter":54,"refName":120,"commitSha":121,"skillDirectory":122,"forksCount":14,"repositoryHtmlUrl":123,"repositoryHomepageUrl":6,"ownerHtmlUrl":124,"ownerBlogUrl":6,"ownerDescription":125,"updatedAt":126,"install":127,"resources":140},"01M6CSVFX50VE7WXX8C6X0XSY2","volontariapp-scaffold-microservice",null,"Playbook opérationnel pas-à-pas pour créer et raccorder un nouveau domaine\u002Fmicroservice de bout en bout (proto, domain package, ms-*, outbox, worker, post-processor, gateway, deploy, ci-tools).","Volontariapp\u002Fmeta","Volontariapp","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F263673138?v=4","01M6CSQNQ3J4SKRWA512JQF5K7","VolontariApp","01M6CSQNV8T2M4PR5A22DKHY5T",0,"MIT","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-scaffold-microservice\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49],"volontariapp scaffold microservice","scaffold","microservice","new","de","worker","local","creation","npm-packages","cli","structure","packages","processor","create","api","code","ci","ddd","scaffolding","runner","ms","2026-11-10 10:12:30",false,"---\nname: volontariapp-scaffold-microservice\ndescription: \"Playbook opérationnel pas-à-pas pour créer et raccorder un nouveau domaine\u002Fmicroservice de bout en bout (proto, domain package, ms-*, outbox, worker, post-processor, gateway, deploy, ci-tools).\"\ntype: Playbook\ntitle: \"Scaffolding d'un Nouveau Microservice gRPC et de ses Runners\"\ntags: [scaffolding, microservice, grpc, nestjs, ddd, runners, playbook]\nstatus: stable\npaths:\n  - \"proto-registry\u002Fproto\u002F**\"\n  - \"npm-packages\u002Fpackages\u002F**\"\n  - \"ms-*\u002Fsrc\u002F**\"\n  - \"outbox-runners\u002F**\"\n  - \"workers-runners\u002F**\"\n  - \"post-processors-runner\u002F**\"\n  - \"api-gateway\u002Fsrc\u002F**\"\n  - \"deploy\u002F**\"\n  - \"ci-tools\u002F**\"\nmesh_keys:\n  - scaffold-microservice\n  - new-microservice\n  - create-service\ngenerated:\n  by: claude-code\u002Fagent\n  at: \"2026-10-12T12:18:00Z\"\nverified:\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T11:15:21Z\"\n    digest: 1d3425728779bb78\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T11:53:21Z\"\n    digest: 3c8471681c92d4c8\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T12:03:29Z\"\n    digest: 827e2dcf344dda7d\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T12:07:08Z\"\n    digest: 140fee1bc59cbf4d\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T12:18:56Z\"\n    digest: d9c18f95209c0701\n  - by: claude-code\u002Fagent\n    at: \"2026-11-08T12:28:00Z\"\n    digest: 9c6245202a161167\nsources:\n  - id: doc-creation\n    kind: local_file\n    resource: docs\u002Fmatching\u002F07-creation-du-microservice.md\n    title: Inventaire exhaustif de création de microservice\n  - id: agent-md\n    kind: local_file\n    resource: AGENT.md\n    title: \"AGENT.md (structure de microservice et règles d'or)\"\n  - id: outbox-script\n    kind: local_file\n    resource: outbox-runners\u002Fscripts\u002Fcreate-outbox.sh\n    title: create-outbox.sh\n  - id: compose\n    kind: local_file\n    resource: ci-tools\u002Fdocker-compose.yml\n    title: ci-tools\u002Fdocker-compose.yml\n  - id: sync-mig\n    kind: local_file\n    resource: scripts\u002Fcli\u002Fcommands\u002Fsync-migrations.mjs\n    title: sync-migrations.mjs\n---\n\n# Scaffolding d'un Nouveau Microservice gRPC et de ses Runners\n\n## Quand utiliser ce playbook\n\nUtiliser ce playbook lorsqu'un nouveau bounded context métier nécessite la création d'un microservice dédié et de son écosystème satellite complet :\n- Nouveau domaine métier isolé (ex. `ms-affinity`, `ms-billing`, etc.).\n- Écosystème asynchrone associé : runner Outbox, worker BullMQ, post-processors Redis Streams.\n- Raccordement Edge : exposition des routes REST dans `api-gateway`.\n- Déploiement et infrastructure : base PostgreSQL dédiée, manifests Kubernetes K3s\u002FArgoCD, NetworkPolicies, et configuration locale `docker-compose`.\n\n---\n\n## Règles d'or d'architecture\n\n1. **Respect absolu des deux STOPs bloquants** :\n   - **Premier STOP** : `proto-registry` (attente PR automatique dans `npm-packages` générée par la CI).\n   - **Second STOP** : `npm-packages` (attente release NPM publiée par la CI).\n   - **INTERDICTION FORMELLE** d'implémenter les microservices ou passerelles consommateurs en avance avec du casting fictif (`as unknown as Type` ou `any`).\n2. **Clean Architecture & DDD strict** :\n   - Le microservice `ms-*` est une coquille d'infrastructure mince. Toute la logique métier réside dans `@volontariapp\u002Fdomain-\u003Cnom>`[^agent-md].\n3. **Isolation des données** :\n   - Chaque microservice dispose de sa base PostgreSQL dédiée. Aucune requête SQL inter-bases n'est permise.\n4. **Sécurité et moindre privilège dès le premier commit** :\n   - Manifests Kubernetes durcis **PSA Restricted**, NetworkPolicies **default-deny**, secrets scellés asymétriquement via `kubeseal` (aucun secret en clair dans Git).\n\n---\n\n## Procédure pas-à-pas\n\n### Étape 1 : Contrats Protobuf dans `proto-registry` (🛑 PREMIER STOP)\n\nDans le dépôt `proto-registry`[^doc-creation] :\n1. Créer le dossier `proto\u002Fvolontariapp\u002F\u003Cdomaine>\u002F` avec les 5 fichiers conventionnels :\n   - `\u003Cdomaine>.proto` : Modèles d'entités du domaine.\n   - `\u003Cdomaine>.command.proto` : Messages des commandes RPC d'écriture.\n   - `\u003Cdomaine>.query.proto` : Messages des requêtes RPC de lecture.\n   - `\u003Cdomaine>.responses.proto` : Messages de réponse RPC.\n   - `\u003Cdomaine>.services.proto` : Définition des services gRPC (`\u003CDomaine>CommandService` et `\u003CDomaine>QueryService`).\n2. Vérifier la conformité du contrat :\n   ```bash\n   cd proto-registry\n   buf lint\n   buf breaking --against '.git#branch=main'\n   ```\n3. **🛑 STOP IMMÉDIAT** : Ouvrir la Pull Request sur `proto-registry`. Attendre le merge sur `main`. La CI déclenche la génération automatique de la PR dans `npm-packages` (`contracts` et `contracts-nest`).\n\n---\n\n### Étape 2 : Domaine et Messagerie dans `npm-packages` (🛑 SECOND STOP)\n\nUne fois la PR Protobuf générée dans `npm-packages`[^doc-creation] :\n1. **Création du package de domaine** `packages\u002Fdomain-\u003Cdomaine>\u002F` (prendre modèle sur `domain-social`) :\n   - Entités du domaine (`*Entity`), modèles TypeORM, interfaces de repository.\n   - Services de logique métier pure.\n   - Migrations de test sous `src\u002Ftest\u002Fmigrations\u002F{common,domain}\u002F`.\n2. **Définition des flux asynchrones dans `packages\u002Fmessaging\u002F`** :\n   - Déclarer les payloads et queues sous `src\u002Fjobs\u002F\u003Cdomaine>\u002F`.\n   - Enregistrer les types dans `JobRegistry` et `JobMessagingType`.\n   - Déclarer les noms de streams dans `packages\u002Fshared\u002Fsrc\u002Fenums\u002Fstreams.enum.ts`.\n   - Configurer le mapping WebSocket dans `packages\u002Fmessaging\u002Fsrc\u002Fwebsockets\u002Fevents\u002Fmapping.ts` (`JOB_TO_EVENT_MAPPING` et `EVENT_EVENT_TO_WS_EVENT_MAPPING`).\n3. **Validation et Versionnage** :\n   ```bash\n   yarn build && yarn test\n   yarn changeset add\n   yarn changeset version\n   ```\n4. **🛑 STOP IMMÉDIAT** : Passer la main au Lead Dev pour pousser sur PR et attendre la publication NPM par la CI (`@volontariapp\u002Fdomain-\u003Cdomaine>`, `@volontariapp\u002Fmessaging`, etc.).\n\n---\n\n### Étape 3 : Scaffolding du microservice `ms-\u003Cdomaine>`\n\n1. Créer le dépôt `ms-\u003Cdomaine>` (prendre modèle sur `ms-social` ou `ms-user`)[^doc-creation] :\n   - Initialiser les dépendances via `yarn up` sur les nouveaux paquets publiés.\n   - Copier `ci-tools\u002Ftemplates\u002Fdependabot\u002Fservice.yml` dans `.github\u002Fdependabot.yml` (retirer le bloc `docker` sans Dockerfile). Le job `security` (Trivy) est déjà fourni par `service-ci.yml`, rien à ajouter dans le `ci.yml`. Ajouter en dernier job du `ci.yml` un `notify-ready` (`needs:` tous les autres jobs, `if: ${{ !failure() && !cancelled() && github.event_name == 'pull_request' }}`, `permissions` `issues: write` et `pull-requests: write`, `uses: Volontariapp\u002Fci-tools\u002F.github\u002Fworkflows\u002Fpr-ready-notify.yml@main`, `with: channel: backend`, `secrets: inherit`) : détail dans `volontariapp-ci-tools`.\n2. **Bootstrap et Observabilité** :\n   - `src\u002Fmain.ts` : Démarrage hybride (serveur gRPC sur port 3000 + serveur HTTP Express pour la sonde `\u002Fhealth`).\n   - `src\u002Ftracing.ts` : Initialisation du SDK OpenTelemetry (Datadog OTLP) avant l'instanciation de NestJS.\n   - `src\u002Fapp.module.ts` : Enregistrement de `AppConfigModule`, `DatabaseModule`, `HealthModule`, `GrpcValidationPipe` et `GrpcInternalGuard` global[^agent-md].\n3. **Configuration & Data Source TypeORM** :\n   - `src\u002Fconfig\u002Fdata-source.ts` : Déclaration de `AppDataSource` référençant les entités du domaine et le glob des migrations.\n   - `src\u002Fmigrations\u002Fcommon\u002F` : Récupérer les migrations partagées via `yarn meta sync-migrations`[^sync-mig].\n   - `src\u002Fmigrations\u002Fdomain\u002F` : Déposer la migration initiale de schéma métier.\n4. **Contrôleurs CQRS** :\n   - Contrôleurs séparés pour les commandes (`BaseCommandController` avec `withFallback`) et les requêtes de lecture.\n   - Mappers stricts sans conversion magique.\n   - Pagination : copier `src\u002Fcommon\u002Fdto\u002Fpagination.dto.ts` de `ms-user` ou `ms-social` (`PaginationRequestDTO` validé, `MAX_PAGINATION_LIMIT`) et l'utiliser dans toute requête de liste avec `@ValidateNested() @Type(...)` ; défaut page 1 \u002F limit 10 dans le contrôleur. Voir l'étape 2 de la skill `volontariapp-grpc-microservice`.\n5. **Matrice de tests e2e** :\n   - Créer `e2e-matrix.json` dans `ms-\u003Cdomaine>` et ajouter le nouveau service aux fichiers `e2e-matrix.json` des services communicants et de l'API Gateway.\n\n---\n\n### Étape 4 : Démon Outbox (`outbox-runners\u002F`)\n\n1. Utiliser le script de génération officiel[^outbox-script] :\n   ```bash\n   cd outbox-runners\n   .\u002Fscripts\u002Fcreate-outbox.sh\n   # Indiquer le nom du domaine (ex. 'affinity')\n   ```\n2. Le script génère `outbox-\u003Cdomaine>\u002F` surveillant les tables `jobs_outbox` et `event_queue` de la base du microservice.\n3. Vérifier les targets Redis Streams et BullMQ dans la configuration.\n4. Rien à ajouter côté CI pour un nouveau domaine : le `ci.yml` de `outbox-runners`, `workers-runners` et `post-processors-runner` porte déjà un job `notify-ready` (`needs: [ci]`, `ci` étant l'appel unique à `runner-pipeline.yml`). Ces `ci.yml` listent leurs secrets au lieu de `secrets: inherit` : `DISCORD_WEBHOOK_BACKEND`, `DISCORD_WEBHOOK_FRONTEND` et `ORG_REPO_TOKEN` y sont passés un par un.\n\n---\n\n### Étape 5 : Flotte de Workers BullMQ (`workers-runners\u002F`)\n\n1. Créer le répertoire `workers-runners\u002Fworker-\u003Cdomaine>\u002F` (prendre modèle sur `worker-social`)[^doc-creation].\n2. Implémenter deux classes étanches dérivées de `BaseWorker` :\n   - `\u003Cdomaine>.worker.ts` pour la file nominale.\n   - `fallback-\u003Cdomaine>.worker.ts` pour la file de fallback dégradée.\n3. Développer les handlers de jobs implémentant l'interface `IJobHandler`.\n4. Injecter les certificats\u002Fclés de signature interne sous `certs\u002F` pour permettre au worker d'appeler d'autres microservices via gRPC en tant que système.\n\n---\n\n### Étape 6 : Consommateurs Post-Processors (`post-processors-runner\u002F`)\n\n1. Créer `post-processors-runner\u002Fpost-processor-\u003Cdomaine>\u002F` (modèle `post-processor-social`)[^doc-creation].\n2. Déclarer les post-processors métier avec groupes de consommateurs dédiés (`options\u002F*.options.ts`).\n3. **Composants critiques obligatoires** :\n   - Enregistrer impérativement `JobOutboxSuccessPostProcessor` et `JobOutboxFailedPostProcessor` dans `post-processors.module.ts`. Sans eux, les lignes `jobs_outbox` ne sont jamais purgées et les notifications WebSocket ne sont jamais diffusées.\n\n---\n\n### Étape 7 : Raccordement API Gateway Edge (`api-gateway\u002F`)\n\nDans le dépôt `api-gateway` :\n1. Créer le module `src\u002Fmodules\u002F\u003Cdomaine>\u002F`.\n2. Implémenter le contrôleur REST `@GatewayController('\u003Cdomaine>')` :\n   - DTO Swagger complets avec décorateurs `class-validator`, qui `implements` les types `\u003CX>Request` de `@volontariapp\u002Fcontracts` (`npm-packages\u002Fpackages\u002Fcontracts\u002Fsrc\u002Fgateway\u002F\u003Cdomaine>\u002F{request,response}`, partagés avec nativapp). Les créer d'abord dans npm-packages (règle du STOP) s'ils n'existent pas.\n   - Propagation de la métadonnée interne d'autorisation : `req['internalMetadata']`.\n   - Gestion des codes de retour (HTTP 200 standard, HTTP 206 `FALLBACK_ACTIVATED` en cas de mode dégradé).\n3. Déclarer le client gRPC et le token d'injection correspondant dans `src\u002Fgrpc\u002F`.\n\n---\n\n### Étape 8 : Déploiement GitOps Kubernetes (`deploy\u002F`)\n\nDans le dépôt `deploy` :\n1. **Manifests de base** sous `deploy\u002Fapps\u002Fbase\u002Fms-\u003Cdomaine>\u002F` :\n   - `deployment.yaml` (microservice principal).\n   - `deployment-outbox.yaml` (démon outbox connecté au `redis-master`).\n   - `deployment-worker.yaml` (worker BullMQ).\n   - `deployment-post-processor.yaml` (consommateurs Redis Streams).\n   - `service.yaml` (exposition gRPC port 3000).\n   - `kustomization.yaml` (durcissement PSA Restricted : `readOnlyRootFilesystem: true`, `runAsNonRoot: true`, `drop: [ALL]`).\n2. **Base de données PostgreSQL** :\n   - Déclarer l'instance sous `deploy\u002Finfrastructure\u002Fdatabases\u002Fms-\u003Cdomaine>\u002F`.\n3. **Secrets scellés** :\n   - Sceller les identifiants de base et les clés privées via `kubeseal` (playbook `volontariapp-sealed-secrets`).\n4. **NetworkPolicies (Default-Deny)** :\n   - Autoriser l'ingress depuis `api-gateway` sur le port 3000.\n   - Autoriser l'egress des pods uniquement vers PostgreSQL et Redis.\n   - Bloquer tout le reste par défaut.\n5. **Application ArgoCD** :\n   - Déclarer l'application sous `deploy\u002Finfrastructure\u002Fargocd\u002F`.\n\n---\n\n### Étape 9 : Outillage Local & Synchronisation CI (`ci-tools\u002F`)\n\n1. **Docker Compose Local** :\n   - Ajouter l'instance PostgreSQL (`postgres-\u003Cdomaine>`) sur un port dédié (ex. 5437 pour storage, 5438 pour ranking) dans `ci-tools\u002Fdocker-compose.yml`[^compose]. Le service `ms-\u003Cdomaine>-migration` ne s'ajoute qu'une fois l'image GHCR publiée (l'E2E tire toutes les images du profil `migrations`).\n   - Déclarer le conteneur de migration `\u003Cdomaine>-migration`.\n2. **Script de synchronisation** :\n   - Déclarer le nouveau microservice dans `repos.json` (`repos` et `units`, avec `migrations: true`, `certs: true`) : les commandes `sync-migrations`, `migrate`, `certs`, `start` le lisent[^sync-mig].\n3. **Gouvernance et Hooks** :\n   - Référencer le service dans [AGENT.md](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002FAGENT.md) et [AGENTS.md](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002FAGENTS.md).\n   - Déclarer le nouveau chemin dans [.agents\u002Fmesh-mcp.toml](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002F.agents\u002Fmesh-mcp.toml).\n   - Exécuter `.\u002Fscripts\u002Finstall-skill-hooks.sh` pour armer les hooks pre-commit sur le nouveau dépôt.\n\n---\n\n### Étape 10 : Intégration Client Mobile (`nativapp\u002F`)\n\nDans `nativapp` :\n1. Développer le hook TanStack Query `use\u003CDomaine>` (discrimination du code `FALLBACK_ACTIVATED` en cas de 206).\n2. Brancher le listener WebSocket dans `src\u002Fhooks\u002FuseNotificationHandlers.ts` pour invalider le cache dès réception de la notification de complétion du job.\n\n---\n\n## Checklist de validation finale\n\n- [ ] Les 5 fichiers `.proto` sont créés et validés par `buf lint` et `buf breaking` (Premier STOP validé).\n- [ ] Le package `@volontariapp\u002Fdomain-\u003Cdomaine>` et les contrats de messagerie sont publiés sur NPM (Second STOP validé).\n- [ ] Le microservice `ms-\u003Cdomaine>` démarre en mode hybride (gRPC 3000 + `\u002Fhealth`) et applique ses migrations sans erreur.\n- [ ] L'Outbox runner est généré via `create-outbox.sh`[^outbox-script] et connecté à Redis.\n- [ ] Les workers implémentent les deux files (nominale et fallback dégradé).\n- [ ] `JobOutboxSuccessPostProcessor` et `JobOutboxFailedPostProcessor` sont déclarés dans le post-processor[^doc-creation].\n- [ ] L'API Gateway expose la route avec `@GatewayController` et propage `req['internalMetadata']`.\n- [ ] Les manifests K8s respectent PSA Restricted et les NetworkPolicies bloquent tout trafic non explicitement autorisé.\n- [ ] La base locale est déclarée dans `ci-tools\u002Fdocker-compose.yml`[^compose] et déclarée dans `repos.json` (`yarn meta manifest` valide la cohérence avec `.gitignore`)[^sync-mig].\n- [ ] Les hooks pre-commit sont installés via `.\u002Fscripts\u002Finstall-skill-hooks.sh`.\n\n---\n\n## Références\n\n[^doc-creation]: docs\u002Fmatching\u002F07-creation-du-microservice.md\n[^agent-md]: AGENT.md\n[^outbox-script]: outbox-runners\u002Fscripts\u002Fcreate-outbox.sh\n[^compose]: ci-tools\u002Fdocker-compose.yml\n[^sync-mig]: scripts\u002Fcli\u002Fcommands\u002Fsync-migrations.mjs\n","# Scaffolding d'un Nouveau Microservice gRPC et de ses Runners\n\n## Quand utiliser ce playbook\n\nUtiliser ce playbook lorsqu'un nouveau bounded context métier nécessite la création d'un microservice dédié et de son écosystème satellite complet :\n- Nouveau domaine métier isolé (ex. `ms-affinity`, `ms-billing`, etc.).\n- Écosystème asynchrone associé : runner Outbox, worker BullMQ, post-processors Redis Streams.\n- Raccordement Edge : exposition des routes REST dans `api-gateway`.\n- Déploiement et infrastructure : base PostgreSQL dédiée, manifests Kubernetes K3s\u002FArgoCD, NetworkPolicies, et configuration locale `docker-compose`.\n\n---\n\n## Règles d'or d'architecture\n\n1. **Respect absolu des deux STOPs bloquants** :\n   - **Premier STOP** : `proto-registry` (attente PR automatique dans `npm-packages` générée par la CI).\n   - **Second STOP** : `npm-packages` (attente release NPM publiée par la CI).\n   - **INTERDICTION FORMELLE** d'implémenter les microservices ou passerelles consommateurs en avance avec du casting fictif (`as unknown as Type` ou `any`).\n2. **Clean Architecture & DDD strict** :\n   - Le microservice `ms-*` est une coquille d'infrastructure mince. Toute la logique métier réside dans `@volontariapp\u002Fdomain-\u003Cnom>`[^agent-md].\n3. **Isolation des données** :\n   - Chaque microservice dispose de sa base PostgreSQL dédiée. Aucune requête SQL inter-bases n'est permise.\n4. **Sécurité et moindre privilège dès le premier commit** :\n   - Manifests Kubernetes durcis **PSA Restricted**, NetworkPolicies **default-deny**, secrets scellés asymétriquement via `kubeseal` (aucun secret en clair dans Git).\n\n---\n\n## Procédure pas-à-pas\n\n### Étape 1 : Contrats Protobuf dans `proto-registry` (🛑 PREMIER STOP)\n\nDans le dépôt `proto-registry`[^doc-creation] :\n1. Créer le dossier `proto\u002Fvolontariapp\u002F\u003Cdomaine>\u002F` avec les 5 fichiers conventionnels :\n   - `\u003Cdomaine>.proto` : Modèles d'entités du domaine.\n   - `\u003Cdomaine>.command.proto` : Messages des commandes RPC d'écriture.\n   - `\u003Cdomaine>.query.proto` : Messages des requêtes RPC de lecture.\n   - `\u003Cdomaine>.responses.proto` : Messages de réponse RPC.\n   - `\u003Cdomaine>.services.proto` : Définition des services gRPC (`\u003CDomaine>CommandService` et `\u003CDomaine>QueryService`).\n2. Vérifier la conformité du contrat :\n   ```bash\n   cd proto-registry\n   buf lint\n   buf breaking --against '.git#branch=main'\n   ```\n3. **🛑 STOP IMMÉDIAT** : Ouvrir la Pull Request sur `proto-registry`. Attendre le merge sur `main`. La CI déclenche la génération automatique de la PR dans `npm-packages` (`contracts` et `contracts-nest`).\n\n---\n\n### Étape 2 : Domaine et Messagerie dans `npm-packages` (🛑 SECOND STOP)\n\nUne fois la PR Protobuf générée dans `npm-packages`[^doc-creation] :\n1. **Création du package de domaine** `packages\u002Fdomain-\u003Cdomaine>\u002F` (prendre modèle sur `domain-social`) :\n   - Entités du domaine (`*Entity`), modèles TypeORM, interfaces de repository.\n   - Services de logique métier pure.\n   - Migrations de test sous `src\u002Ftest\u002Fmigrations\u002F{common,domain}\u002F`.\n2. **Définition des flux asynchrones dans `packages\u002Fmessaging\u002F`** :\n   - Déclarer les payloads et queues sous `src\u002Fjobs\u002F\u003Cdomaine>\u002F`.\n   - Enregistrer les types dans `JobRegistry` et `JobMessagingType`.\n   - Déclarer les noms de streams dans `packages\u002Fshared\u002Fsrc\u002Fenums\u002Fstreams.enum.ts`.\n   - Configurer le mapping WebSocket dans `packages\u002Fmessaging\u002Fsrc\u002Fwebsockets\u002Fevents\u002Fmapping.ts` (`JOB_TO_EVENT_MAPPING` et `EVENT_EVENT_TO_WS_EVENT_MAPPING`).\n3. **Validation et Versionnage** :\n   ```bash\n   yarn build && yarn test\n   yarn changeset add\n   yarn changeset version\n   ```\n4. **🛑 STOP IMMÉDIAT** : Passer la main au Lead Dev pour pousser sur PR et attendre la publication NPM par la CI (`@volontariapp\u002Fdomain-\u003Cdomaine>`, `@volontariapp\u002Fmessaging`, etc.).\n\n---\n\n### Étape 3 : Scaffolding du microservice `ms-\u003Cdomaine>`\n\n1. Créer le dépôt `ms-\u003Cdomaine>` (prendre modèle sur `ms-social` ou `ms-user`)[^doc-creation] :\n   - Initialiser les dépendances via `yarn up` sur les nouveaux paquets publiés.\n   - Copier `ci-tools\u002Ftemplates\u002Fdependabot\u002Fservice.yml` dans `.github\u002Fdependabot.yml` (retirer le bloc `docker` sans Dockerfile). Le job `security` (Trivy) est déjà fourni par `service-ci.yml`, rien à ajouter dans le `ci.yml`. Ajouter en dernier job du `ci.yml` un `notify-ready` (`needs:` tous les autres jobs, `if: ${{ !failure() && !cancelled() && github.event_name == 'pull_request' }}`, `permissions` `issues: write` et `pull-requests: write`, `uses: Volontariapp\u002Fci-tools\u002F.github\u002Fworkflows\u002Fpr-ready-notify.yml@main`, `with: channel: backend`, `secrets: inherit`) : détail dans `volontariapp-ci-tools`.\n2. **Bootstrap et Observabilité** :\n   - `src\u002Fmain.ts` : Démarrage hybride (serveur gRPC sur port 3000 + serveur HTTP Express pour la sonde `\u002Fhealth`).\n   - `src\u002Ftracing.ts` : Initialisation du SDK OpenTelemetry (Datadog OTLP) avant l'instanciation de NestJS.\n   - `src\u002Fapp.module.ts` : Enregistrement de `AppConfigModule`, `DatabaseModule`, `HealthModule`, `GrpcValidationPipe` et `GrpcInternalGuard` global[^agent-md].\n3. **Configuration & Data Source TypeORM** :\n   - `src\u002Fconfig\u002Fdata-source.ts` : Déclaration de `AppDataSource` référençant les entités du domaine et le glob des migrations.\n   - `src\u002Fmigrations\u002Fcommon\u002F` : Récupérer les migrations partagées via `yarn meta sync-migrations`[^sync-mig].\n   - `src\u002Fmigrations\u002Fdomain\u002F` : Déposer la migration initiale de schéma métier.\n4. **Contrôleurs CQRS** :\n   - Contrôleurs séparés pour les commandes (`BaseCommandController` avec `withFallback`) et les requêtes de lecture.\n   - Mappers stricts sans conversion magique.\n   - Pagination : copier `src\u002Fcommon\u002Fdto\u002Fpagination.dto.ts` de `ms-user` ou `ms-social` (`PaginationRequestDTO` validé, `MAX_PAGINATION_LIMIT`) et l'utiliser dans toute requête de liste avec `@ValidateNested() @Type(...)` ; défaut page 1 \u002F limit 10 dans le contrôleur. Voir l'étape 2 de la skill `volontariapp-grpc-microservice`.\n5. **Matrice de tests e2e** :\n   - Créer `e2e-matrix.json` dans `ms-\u003Cdomaine>` et ajouter le nouveau service aux fichiers `e2e-matrix.json` des services communicants et de l'API Gateway.\n\n---\n\n### Étape 4 : Démon Outbox (`outbox-runners\u002F`)\n\n1. Utiliser le script de génération officiel[^outbox-script] :\n   ```bash\n   cd outbox-runners\n   .\u002Fscripts\u002Fcreate-outbox.sh\n   # Indiquer le nom du domaine (ex. 'affinity')\n   ```\n2. Le script génère `outbox-\u003Cdomaine>\u002F` surveillant les tables `jobs_outbox` et `event_queue` de la base du microservice.\n3. Vérifier les targets Redis Streams et BullMQ dans la configuration.\n4. Rien à ajouter côté CI pour un nouveau domaine : le `ci.yml` de `outbox-runners`, `workers-runners` et `post-processors-runner` porte déjà un job `notify-ready` (`needs: [ci]`, `ci` étant l'appel unique à `runner-pipeline.yml`). Ces `ci.yml` listent leurs secrets au lieu de `secrets: inherit` : `DISCORD_WEBHOOK_BACKEND`, `DISCORD_WEBHOOK_FRONTEND` et `ORG_REPO_TOKEN` y sont passés un par un.\n\n---\n\n### Étape 5 : Flotte de Workers BullMQ (`workers-runners\u002F`)\n\n1. Créer le répertoire `workers-runners\u002Fworker-\u003Cdomaine>\u002F` (prendre modèle sur `worker-social`)[^doc-creation].\n2. Implémenter deux classes étanches dérivées de `BaseWorker` :\n   - `\u003Cdomaine>.worker.ts` pour la file nominale.\n   - `fallback-\u003Cdomaine>.worker.ts` pour la file de fallback dégradée.\n3. Développer les handlers de jobs implémentant l'interface `IJobHandler`.\n4. Injecter les certificats\u002Fclés de signature interne sous `certs\u002F` pour permettre au worker d'appeler d'autres microservices via gRPC en tant que système.\n\n---\n\n### Étape 6 : Consommateurs Post-Processors (`post-processors-runner\u002F`)\n\n1. Créer `post-processors-runner\u002Fpost-processor-\u003Cdomaine>\u002F` (modèle `post-processor-social`)[^doc-creation].\n2. Déclarer les post-processors métier avec groupes de consommateurs dédiés (`options\u002F*.options.ts`).\n3. **Composants critiques obligatoires** :\n   - Enregistrer impérativement `JobOutboxSuccessPostProcessor` et `JobOutboxFailedPostProcessor` dans `post-processors.module.ts`. Sans eux, les lignes `jobs_outbox` ne sont jamais purgées et les notifications WebSocket ne sont jamais diffusées.\n\n---\n\n### Étape 7 : Raccordement API Gateway Edge (`api-gateway\u002F`)\n\nDans le dépôt `api-gateway` :\n1. Créer le module `src\u002Fmodules\u002F\u003Cdomaine>\u002F`.\n2. Implémenter le contrôleur REST `@GatewayController('\u003Cdomaine>')` :\n   - DTO Swagger complets avec décorateurs `class-validator`, qui `implements` les types `\u003CX>Request` de `@volontariapp\u002Fcontracts` (`npm-packages\u002Fpackages\u002Fcontracts\u002Fsrc\u002Fgateway\u002F\u003Cdomaine>\u002F{request,response}`, partagés avec nativapp). Les créer d'abord dans npm-packages (règle du STOP) s'ils n'existent pas.\n   - Propagation de la métadonnée interne d'autorisation : `req['internalMetadata']`.\n   - Gestion des codes de retour (HTTP 200 standard, HTTP 206 `FALLBACK_ACTIVATED` en cas de mode dégradé).\n3. Déclarer le client gRPC et le token d'injection correspondant dans `src\u002Fgrpc\u002F`.\n\n---\n\n### Étape 8 : Déploiement GitOps Kubernetes (`deploy\u002F`)\n\nDans le dépôt `deploy` :\n1. **Manifests de base** sous `deploy\u002Fapps\u002Fbase\u002Fms-\u003Cdomaine>\u002F` :\n   - `deployment.yaml` (microservice principal).\n   - `deployment-outbox.yaml` (démon outbox connecté au `redis-master`).\n   - `deployment-worker.yaml` (worker BullMQ).\n   - `deployment-post-processor.yaml` (consommateurs Redis Streams).\n   - `service.yaml` (exposition gRPC port 3000).\n   - `kustomization.yaml` (durcissement PSA Restricted : `readOnlyRootFilesystem: true`, `runAsNonRoot: true`, `drop: [ALL]`).\n2. **Base de données PostgreSQL** :\n   - Déclarer l'instance sous `deploy\u002Finfrastructure\u002Fdatabases\u002Fms-\u003Cdomaine>\u002F`.\n3. **Secrets scellés** :\n   - Sceller les identifiants de base et les clés privées via `kubeseal` (playbook `volontariapp-sealed-secrets`).\n4. **NetworkPolicies (Default-Deny)** :\n   - Autoriser l'ingress depuis `api-gateway` sur le port 3000.\n   - Autoriser l'egress des pods uniquement vers PostgreSQL et Redis.\n   - Bloquer tout le reste par défaut.\n5. **Application ArgoCD** :\n   - Déclarer l'application sous `deploy\u002Finfrastructure\u002Fargocd\u002F`.\n\n---\n\n### Étape 9 : Outillage Local & Synchronisation CI (`ci-tools\u002F`)\n\n1. **Docker Compose Local** :\n   - Ajouter l'instance PostgreSQL (`postgres-\u003Cdomaine>`) sur un port dédié (ex. 5437 pour storage, 5438 pour ranking) dans `ci-tools\u002Fdocker-compose.yml`[^compose]. Le service `ms-\u003Cdomaine>-migration` ne s'ajoute qu'une fois l'image GHCR publiée (l'E2E tire toutes les images du profil `migrations`).\n   - Déclarer le conteneur de migration `\u003Cdomaine>-migration`.\n2. **Script de synchronisation** :\n   - Déclarer le nouveau microservice dans `repos.json` (`repos` et `units`, avec `migrations: true`, `certs: true`) : les commandes `sync-migrations`, `migrate`, `certs`, `start` le lisent[^sync-mig].\n3. **Gouvernance et Hooks** :\n   - Référencer le service dans [AGENT.md](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002FAGENT.md) et [AGENTS.md](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002FAGENTS.md).\n   - Déclarer le nouveau chemin dans [.agents\u002Fmesh-mcp.toml](file:\u002F\u002F\u002FUsers\u002Fvictoragahi\u002FDeveloper\u002Fmeta\u002F.agents\u002Fmesh-mcp.toml).\n   - Exécuter `.\u002Fscripts\u002Finstall-skill-hooks.sh` pour armer les hooks pre-commit sur le nouveau dépôt.\n\n---\n\n### Étape 10 : Intégration Client Mobile (`nativapp\u002F`)\n\nDans `nativapp` :\n1. Développer le hook TanStack Query `use\u003CDomaine>` (discrimination du code `FALLBACK_ACTIVATED` en cas de 206).\n2. Brancher le listener WebSocket dans `src\u002Fhooks\u002FuseNotificationHandlers.ts` pour invalider le cache dès réception de la notification de complétion du job.\n\n---\n\n## Checklist de validation finale\n\n- [ ] Les 5 fichiers `.proto` sont créés et validés par `buf lint` et `buf breaking` (Premier STOP validé).\n- [ ] Le package `@volontariapp\u002Fdomain-\u003Cdomaine>` et les contrats de messagerie sont publiés sur NPM (Second STOP validé).\n- [ ] Le microservice `ms-\u003Cdomaine>` démarre en mode hybride (gRPC 3000 + `\u002Fhealth`) et applique ses migrations sans erreur.\n- [ ] L'Outbox runner est généré via `create-outbox.sh`[^outbox-script] et connecté à Redis.\n- [ ] Les workers implémentent les deux files (nominale et fallback dégradé).\n- [ ] `JobOutboxSuccessPostProcessor` et `JobOutboxFailedPostProcessor` sont déclarés dans le post-processor[^doc-creation].\n- [ ] L'API Gateway expose la route avec `@GatewayController` et propage `req['internalMetadata']`.\n- [ ] Les manifests K8s respectent PSA Restricted et les NetworkPolicies bloquent tout trafic non explicitement autorisé.\n- [ ] La base locale est déclarée dans `ci-tools\u002Fdocker-compose.yml`[^compose] et déclarée dans `repos.json` (`yarn meta manifest` valide la cohérence avec `.gitignore`)[^sync-mig].\n- [ ] Les hooks pre-commit sont installés via `.\u002Fscripts\u002Finstall-skill-hooks.sh`.\n\n---\n\n## Références\n\n[^doc-creation]: docs\u002Fmatching\u002F07-creation-du-microservice.md\n[^agent-md]: AGENT.md\n[^outbox-script]: outbox-runners\u002Fscripts\u002Fcreate-outbox.sh\n[^compose]: ci-tools\u002Fdocker-compose.yml\n[^sync-mig]: scripts\u002Fcli\u002Fcommands\u002Fsync-migrations.mjs\n",{"name":5,"tags":55,"type":60,"paths":61,"title":71,"status":72,"sources":73,"verified":94,"generated":114,"mesh_keys":116,"description":7},[47,31,56,57,46,58,59],"grpc","nestjs","runners","playbook","Playbook",[62,63,64,65,66,67,68,69,70],"proto-registry\u002Fproto\u002F**","npm-packages\u002Fpackages\u002F**","ms-*\u002Fsrc\u002F**","outbox-runners\u002F**","workers-runners\u002F**","post-processors-runner\u002F**","api-gateway\u002Fsrc\u002F**","deploy\u002F**","ci-tools\u002F**","Scaffolding d'un Nouveau Microservice gRPC et de ses Runners","stable",[74,79,83,87,90],{"id":75,"kind":76,"title":77,"resource":78},"doc-creation","local_file","Inventaire exhaustif de création de microservice","docs\u002Fmatching\u002F07-creation-du-microservice.md",{"id":80,"kind":76,"title":81,"resource":82},"agent-md","AGENT.md (structure de microservice et règles d'or)","AGENT.md",{"id":84,"kind":76,"title":85,"resource":86},"outbox-script","create-outbox.sh","outbox-runners\u002Fscripts\u002Fcreate-outbox.sh",{"id":88,"kind":76,"title":89,"resource":89},"compose","ci-tools\u002Fdocker-compose.yml",{"id":91,"kind":76,"title":92,"resource":93},"sync-mig","sync-migrations.mjs","scripts\u002Fcli\u002Fcommands\u002Fsync-migrations.mjs",[95,99,102,105,108,111],{"at":96,"by":97,"digest":98},"2026-11-08T11:15:21Z","claude-code\u002Fagent","1d3425728779bb78",{"at":100,"by":97,"digest":101},"2026-11-08T11:53:21Z","3c8471681c92d4c8",{"at":103,"by":97,"digest":104},"2026-11-08T12:03:29Z","827e2dcf344dda7d",{"at":106,"by":97,"digest":107},"2026-11-08T12:07:08Z","140fee1bc59cbf4d",{"at":109,"by":97,"digest":110},"2026-11-08T12:18:56Z","d9c18f95209c0701",{"at":112,"by":97,"digest":113},"2026-11-08T12:28:00Z","9c6245202a161167",{"at":115,"by":97},"2026-10-12T12:18:00Z",[117,118,119],"scaffold-microservice","new-microservice","create-service","main","6b8f03b57018fa66da4666071dc17c1577ff45e8",".agents\u002Fskills\u002Fvolontariapp-scaffold-microservice","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta","https:\u002F\u002Fgithub.com\u002FVolontariapp","Volontariapp — Application Web\u002FMobile scalabelle construite sur une architecture microservices événementielle (Event-Driven Architecture), implémentant le Trans","2026-11-10 23:40:22",{"source":8,"skillName":5,"commands":128,"prompt":138,"zipAvailable":139},[129,132,135],{"tool":130,"command":131},"npx","npx skills add Volontariapp\u002Fmeta --skill volontariapp-scaffold-microservice",{"tool":133,"command":134},"bunx","bunx skills add Volontariapp\u002Fmeta --skill volontariapp-scaffold-microservice",{"tool":136,"command":137},"pnpm","pnpm dlx skills add Volontariapp\u002Fmeta --skill volontariapp-scaffold-microservice","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-scaffold-microservice\u002FSKILL.md",true,[141,147,151],{"path":142,"resourceType":143,"resourceTypeDesc":144,"sizeBytes":145,"sourceHtmlUrl":146},"index.md","REFERENCE","参考文档",631,"https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-scaffold-microservice\u002Findex.md",{"path":148,"resourceType":143,"resourceTypeDesc":144,"sizeBytes":149,"sourceHtmlUrl":150},"log.md",25934,"https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-scaffold-microservice\u002Flog.md",{"path":152,"resourceType":143,"resourceTypeDesc":144,"sizeBytes":153,"sourceHtmlUrl":154},"references\u002Flessons.md",1894,"https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-scaffold-microservice\u002Freferences\u002Flessons.md",[156,178,202,226,249,268],{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":162,"publishedAt":50},"01M6CSW3Y5ZHVBF5BX7S5BAVS0","volontariapp-user-account-deletion","Suppression de compte en deux temps (PENDING_DELETION): requestDeletionWithUserDeleted, finalizeDeletion, fan-out de user.deleted vers les domaines et gather ws. A utiliser pour tout changement de domain-user touchant la suppression, le statut ou le cycle de vie d'un user.","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-user-account-deletion\u002FSKILL.md",[],[163,164,165,166,167,168,169,170,33,44,171,172,173,174,175,176,177,37,40],"volontariapp user account deletion","user","account deletion","deletion","cycle","gather","sonnet","pending","claude-code","reference","npm","user-account-deletion","src","en","domain",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":187,"publishedAt":50},"01M6CSVC1ZW30DDFZ8VMEYAAK6","volontariapp-proto-contract-evolution","Modifier un contrat Protobuf de proto-registry (champ, message, enum, RPC) sans casser la compatibilité wire, puis suivre la cascade proto-registry, PR automatique dans npm-packages, publication, consommateurs. À utiliser avant toute édition d'un .proto.","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-proto-contract-evolution\u002FSKILL.md",[184],{"categoryNo":185,"categoryName":186,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000037","律师与法务",[188,189,56,190,44,191,192,40,193,45,194,195,196,173,197,198,199,200,59,201],"evolution","volontariapp proto contract evolution","lint","workflows","analyze","rpc","pr","protobuf","message","registry","sans","sync","yaml","github",{"skillNo":203,"name":204,"nameZh":6,"description":205,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":206,"categories":207,"keywords":211,"publishedAt":50},"01M6CSV99ET2Z9W4W4DAK4CMQP","volontariapp-meta-scripts","Utiliser et faire evoluer la CLI Node de meta (setup, doctor, migrate, certs, repos, bump) et le manifeste repos.json, source unique des repos et unites du workspace.","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-meta-scripts\u002FSKILL.md",[208],{"categoryNo":209,"categoryName":210,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[212,213,214,44,215,171,216,217,218,219,220,221,222,38,223,224,225],"Meta","volontariapp meta scripts","repos","migrate","setup","meta-scripts","json","node","workspace","shell","bump","doctor","draft","install",{"skillNo":227,"name":228,"nameZh":6,"description":229,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":230,"categories":231,"keywords":235,"publishedAt":50},"01M6CSTPHNTGE0WF5CPE8W7ZYQ","volontariapp-implement-async-event-flow","Guide pas-à-pas pour concevoir et implémenter un flux asynchrone complet (messaging -> outbox -> post-processors -> ws-service -> client).","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fvolontariapp-implement-async-event-flow\u002FSKILL.md",[232],{"categoryNo":233,"categoryName":234,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[236,237,238,239,240,241,175,242,243,197,244,245,37,246,247,40,41,248,44,48],"async","implement","volontariapp implement async event flow","flow","event","messaging","mapping","flux","streams","flows","shared","outbox","architecture",{"skillNo":250,"name":251,"nameZh":6,"description":252,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":253,"categories":254,"keywords":258,"publishedAt":50},"01M6CSRQHS0T9955M8CTA5BYJQ","research","Investigate a question against high-trust primary sources and capture the findings as a Markdown file in the repo. Use when the user wants a topic researched, docs or API facts gathered, or reading legwork delegated to a background agent.","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fplugins\u002Fmatt-pocock\u002Fskills\u002Fresearch\u002FSKILL.md",[255],{"categoryNo":256,"categoryName":257,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",[251,43,164,259,260,261,262,263,264,265,266,267],"file","repo","markdown","docs","capture","use","question","trust","investigate",{"skillNo":269,"name":270,"nameZh":6,"description":271,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":272,"categories":273,"keywords":277,"publishedAt":50},"01M6CSRMZ82M1YK96Z4SW1STTD","prototype","Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.","https:\u002F\u002Fgithub.com\u002FVolontariapp\u002Fmeta\u002Fblob\u002Fmain\u002F.agents\u002Fplugins\u002Fmatt-pocock\u002Fskills\u002Fprototype\u002FSKILL.md",[274],{"categoryNo":275,"categoryName":276,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000032","设计师",[270,278,164,279,264,280,265,281,282,283,284,285],"check","ui","look","design","explore","model","build","state"]