EugineKosenko/majordom

Génère un nouveau composant/commande/crate dans le style Rust littéraire org-babel de cet utilisateur (modèle des crates ads-back — un fichier org par commande avec un bloc :tangle squelette, blocs noweb Déclarations-avant-Définitions/Actions, un titre par concept). Utilise-le quand l'utilisateur demande d'ajouter un nouveau composant, une commande, une procédure, une sous-commande CLI, un composant Yew, un module ou un crate dans un projet Rust littéraire org-babel (ads-back, ads-front ou similaire), y compris le câblage d'un tout nouveau crate (config.org/env.org/main.org) dans le config.org fédéré du workspace.

Qu'est-ce que majordom ?

Cette compétence permet de créer de nouveaux composants logiciels (commandes, procédures, sous-commandes CLI, composants Yew ou crates entiers) selon le style Rust littéraire org-babel utilisé dans les projets ads-back et ads-front. Le processus est entièrement guidé par le contenu des fichiers SKILL.md et CLAUDE.md, garantissant une structure cohérente. La compétence prend en charge cinq variantes : procédure/commande dans un crate existant, sous-commande CLI, composant Yew, nouveau crate fédéré, et composant autonome. Elle est conçue pour les projets Rust utilisant org-babel avec des blocs noweb, où chaque fichier org représente une commande ou un composant, et où les fichiers sont organisés selon le principe des déclarations avant les définitions. La compétence assure que chaque nouveau composant suit exactement le même schéma que les composants existants, en termes de structure de fichiers, de conventions de nommage et de gestion des dépendances. Elle inclut également des étapes de vérification automatique après chaque modification : tangle via emacsclient, cargo check, lint org et formatage du texte.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/EugineKosenko/majordom/tree/HEAD/skills/create-cmpnnt

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

create-cmpnnt

Compétence pour créer un nouveau composant (cmpnnt) — commande, procédure, sous-commande, Yew-composant ou crate entier — dans le style littéraire org-babel documenté dans ~/.claude/CLAUDE.md. Basé sur les fichiers réels de code/ads-back (crates/api/create-card.org, crates/api/retrve-card.org, crates/cli/main.org, crates/svc/main.org, config.org racine, env.org).

Étape 0 — détermination du variant

Par défaut (sans arguments explicites), détermine le variant à partir de la demande de l'utilisateur ; en cas d'ambiguïté — pose une question de clarification via AskUserQuestion, ne devine pas en silence :

  • A. Procédure/commande dans un crate existant — cas typique (ex. nouveau handler rocket dans crates/api, nouvelle fonction de bibliothèque dans crates/db). Un nouveau fichier org, sans modification de config.org.
  • B. Sous-commande d'une CLI existante — nouveau fichier <sous-commande>.org (mod) + insertion dans le main.org existant de ce crate (mod, Command:Éléments, Variantes).
  • C. Composant Yew (ads-front) — structure proche de crates/app/marker.org : section "Propriétés" avec les propriétés du composant, blocs Html. Même squelette (Déclarations avant Définition, un titre par concept), autre terminologie des blocs.
  • D. Nouveau crate ("fédéré cargo") — lorsque le composant ne rentre logiquement dans aucun crate existant. Alors, en plus du composant lui-même, il faut config.org, env.org, main.org du nouveau crate et l'enregistrement dans le config.org racine (voir Étape 4).

N'attribue pas le variant D "au cas où" — seulement quand l'utilisateur demande explicitement un nouveau crate, ou quand aucun crate existant ne convient logiquement (et que cela est confirmé par l'utilisateur).

Étape 1 — langue du fichier org

La langue dépend de la situation, non fixée à l'avance. Avant de créer le fichier, regarde la langue des fichiers org voisins dans le répertoire cible (code/ads-back/env.org — en anglais, la plupart des crates/api/*.org — en ukrainien) : si le répertoire a une majorité claire — écris dans la même langue ; si c'est un nouveau répertoire ou si la langue des voisins est ambiguë — demande à l'utilisateur en une question, ne devine pas.

Étape 2 — squelette commun (tous les variants)

Quel que soit le variant, chaque nouveau fichier org avec sa propre cible :tangle :

  1. #+title: ... — nom du composant (dans la langue de l'étape 1).

  2. Si nécessaire — paragraphe avec un lien vers la spécification ([[https://...][spécification]]), comme dans create-card.org.

  3. Premier titre (* Module / * Fichier / * Crate — nom selon l'exemple des fichiers voisins du même répertoire, ce n'est pas strictement fixé) avec un bloc squelette :

    #+begin_src rust :noweb yes :mkdirp yes :tangle src/NOM_DU_FICHIER.rs
      <<Déclarations>>
    
      <<Définitions>>
    #+end_src
    
  4. Immédiatement après le squelette — section * Exécuteur (pour procédure/commande) avec deux blocs : :noweb-ref Déclarations (imports, y compris les types Request/Response de ads_api) et :noweb-ref Définitions (la fonction elle-même pub fn run(...), dont le corps est principalement <<Actions>> à l'intérieur de db::cnnctn().transaction(...), si une transaction est nécessaire).

  5. Chaque petit élément de logique suivant (vérification, obtention d'un champ, insertion dans une table, etc.) — titre séparé */** avec ses propres :noweb-ref Déclarations (si de nouveaux use sont nécessaires) et :noweb-ref Actions — dans cet ordre (déclaration avant utilisation, comme partout ailleurs). Ne regroupe pas toute la logique dans un seul bloc — chaque étape significative doit avoir son propre titre, comme dans create-card.org (15+ titres séparés pour une seule procédure).

  6. Si une étape engendre une fonction auxiliaire (ex. upsert_phone dans create-card.org) — propre :noweb-ref Définitions pour la signature de la fonction, et le corps via un noweb-ref nommé (upsert-phone:Actions), et des sous-titres **/*** pour chaque action à l'intérieur.

Le variant B (sous-commande CLI) diffère en ce qu'il n'y aura pas de nouveau bloc squelette — à la place, ajoute dans le main.org existant trois blocs noweb sans nouveau titre-squelette : :noweb-ref Déclarations (mod nouvelle_sous_commande;), :noweb-sep ",\n" :noweb-ref Command:Éléments (variant enum Command avec champs-arguments), et :noweb yes :noweb-sep ",\n" :noweb-ref Variantes (Command::Variant { ... } => crate::module::run(...)) — chacun dans son propre titre *, nommé par l'action (ex. * Création d'organisation), et l'implémentation elle-même dans un nouveau fichier org de sous-commande séparé selon le squelette commun (étape 2, variant A).

Le variant C (composant Yew) diffère par les noms des sections : au lieu d'"Exécuteur" — section "Propriétés" (struct ...Props, une propriété = un sous-titre **, :noweb-sep ",\n" :noweb-ref NomProps:Propriétés), et section "Composant" (#[function_component(...)], corps — <<Nom:État>>, <<Nom:Effets>>, <<Nom:Gestionnaires>>, html! { <<Nom:Html>> }). Regarde code/ads-front/crates/app/marker.org comme exemple vivant de ce variant.

Étape 3 — fonction main typique (variant D, d'abord)

La première version de main.org d'un nouveau crate doit être la plus simple possible — sans gestion d'erreurs, sans Result, sans async, sans initialisation du logger/env, tant qu'il n'y a pas de besoin spécifique :

#+title: NOM DU CRATE

* Fichier

#+begin_src rust :noweb yes :mkdirp yes :tangle src/main.rs
  <<Déclarations>>

  <<Définitions>>

  fn main() {
      <<Actions>>
  }
#+end_src

<<Actions>> peut d'abord être complètement vide (le nouveau crate ne fait encore rien) — c'est une première étape normale, les titres suivants le remplissent progressivement, comme dans crates/cli/main.org/crates/svc/main.org. La gestion d'erreurs (Result, ?), async, l'initialisation de dotenv/env_logger etc. doivent être ajoutés par des titres séparés plus tard, quand l'étape spécifique le nécessite vraiment — pas à l'avance.

Étape 4 — nouveau crate : config.org et enregistrement dans le config.org fédéré

  1. crates/NOM/config.org — fichier du crate (voir crates/cli/config.org comme exemple) :

    #+title: Fichier =Cargo=
    
    * Fichier
    
    #+begin_src toml :noweb yes :tangle Cargo.toml
      [package]
      name = "NOM"
      version = "0.1.0"
      edition = "2021"
    
      [dependencies]
      <<Dépendances>>
    #+end_src
    

    Chaque dépendance — titre * =nom_du_crate= séparé avec :noweb-ref Dépendances (nom = { workspace = true }), ordonné selon la règle de CLAUDE.md (tiers → forge → crates du projet, sinon — alphabétique). Les blocs * Version =Rust=/* Configuration locale (rust-toolchain.toml/.cargo/config.toml) sont copiés du config.org voisin uniquement si c'est déjà la pratique dans ce répertoire — ne les ajoute pas "au cas où" si aucun crate voisin ne le fait. Si tu copies, le fichier devient multi-cible (plusieurs :tangle différents), donc tous les blocs noweb (y compris Dépendances) passent à des noms préfixés (Cargo:Dépendances, config:Définitions etc., voir CLAUDE.md) — comme dans le config.org racine ci-dessous.

  2. Dans le config.org RACINE (workspace), ajoute un nouveau titre * =NOM= avec deux blocs — selon le modèle des sections * =db=/* =api= à la racine :

    #+begin_src toml :noweb-sep ",\n" :noweb-ref Cargo:Crates
      "crates/NOM"
    #+end_src
    
    #+begin_src toml :noweb-ref Cargo:Dépendances
      NOM = { path = "crates/NOM" }
    #+end_src
    
  3. env.org — si le nouveau crate n'introduit pas ses propres variables d'environnement, ne touche à rien. S'il en introduit — et qu'il existe déjà un env.org racine commun dans le projet — ajoute une nouvelle section * avec son propre :noweb-ref (comme * Accès base de données/* Paramètres =JWT=), plutôt que de créer un fichier séparé. Crée un env.org SÉPARÉ pour le nouveau crate uniquement lorsqu'il s'agit d'un déploiement indépendant (son propre .env, pas le même processus) et qu'aucun env.org commun n'existe. Dans tous les cas, le premier env.org peut rester complètement sans variables spécifiques (peut être sans valeurs, juste le fichier principal) — juste un squelette :

    #+title: Fichier =dotenv=
    
    * Fichier de configuration
    
    #+begin_src conf :noweb yes :tangle .env.example
      <<Définitions>>
    #+end_src
    

    et le remplir avec des sections * =X= parameters spécifiques plus tard, quand les vraies variables apparaissent.

Étape 5 — vérification après chaque modification

Après chaque modification significative de la source org :

  1. Tangle réel via emacsclient --eval (n'écris jamais le contenu des fichiers .rs/.toml/.env.example manuellement — voir la règle globale correspondante).
  2. cargo check -p CRATE (ajoute --target wasm32-unknown-unknown pour ads-front) — zéro avertissement et erreur.
  3. Exécute la compétence org-lint sur le fichier modifié et corrige immédiatement les résultats "CERTAINS", examine les "nécessite vérification".
  4. Pour la prose fraîchement écrite/modifiée — (font-lock-ensure) + org-fill-paragraph via le même emacsclient, pas manuellement.

Ne présente pas le composant comme prêt à l'utilisateur tant que ces quatre points n'ont pas été passés pour chaque fichier org nouveau ou modifié.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

EugineKosenko/majordom

Analyse a Figma .fig file kept in a project's spcfctn/ui/draft. Unpacks and decodes it offline (kiwi), breaks it into sections, screens, text rows and rasters, writes the analysis to spcfctn/ui/*.md, then fetches the author's comments through the figma MCP by link, binds them to screens by geometry, checks that the comments agree with the content of the file and asks the user to clarify what does not. Use when the user asks to analyse, decode or re-read a .fig file or Figma wireframes, or to refresh spcfctn/ui after a new export.

EugineKosenko/majordom

Керування сесіями claude-code-ide.el у живому Emacs через emacsclient headless — старт/continue/resume без блокуючих запитів, безпечна зупинка, перемикання permission-mode і auto-accept, навігація в інтерактивних picker'ах. Використовуй, коли сесія "Мажордом" має підняти, продовжити, зупинити чи інспектувати сесію claude-code-ide для іншого проєкту.

EugineKosenko/majordom

Bootstrap a new project in this user's standard layout — .claude-root, .dir-locals.el (root: org-link abbreviation), code/, spcfctn/code/ (with its own git repository) and a .claude/ directory with its own git repository and a CLAUDE.md that fixes the project's prose language and its short two-letter project code (chosen by the user from options the agent proposes) — and translate any files already present into that language. Use whenever the user asks to create, start, set up, initialise or "оформити" a new project (or to bring an existing bare directory to the standard layout).

EugineKosenko/majordom

Check org/md prose in this user's projects against the prose-formatting conventions in ~/.claude/rules/org-babel.md (~...~ vs =...= markup, acronym casing, /.../ glossary terms, real org-links vs italics/plain text, spaces around / between two markups, trailing newline, fill-column). Use proactively right after editing prose paragraphs in an .org or .md file (in place of manually re-deriving each rule from memory), and whenever the user explicitly asks to check/lint org rules or compares the request to running clippy.

Skills associés