Communitygithub.com

ssunduko/selector-vidéo-produit

Résolvez les sélecteurs en langage naturel `ask "..."` d'un script `.demo` dans l'application réelle via l'extension Claude dans Chrome, et écrivez le fichier `<script>.selectors.json` compagnon. Utilisez-le quand un script a des intentions non résolues, quand la compilation ou l'enregistrement échoue avec « selector(s) still state an intent », ou quand une refonte a cassé des sélecteurs qui fonctionnaient.

Qu'est-ce que selector-vidéo-produit ?

Cette compétence agit comme un résolveur de sélecteurs en langage naturel pour les scripts `.demo` utilisés dans un pipeline de production vidéo. Elle permet à un agent IA (notamment via l'extension Claude dans Chrome) de parcourir les étapes (`beats`) d'un script, de trouver les éléments DOM correspondant aux descriptions textuelles comme `ask "la boîte de message en bas du chat"`, et de générer un fichier `.selectors.json` contenant les sélecteurs concrets (basés sur `data-testid`, `aria-label`, etc.). Cela évite les appels à un modèle pendant l'enregistrement, garantissant une vidéo sans 'temps mort'. La compétence fonctionne en conjonction avec `script.mjs` et `driver.mjs` du pipeline, et nécessite une session Chrome déjà connectée à l'application cible. Si elle ne peut pas résoudre un sélecteur, elle doit s'arrêter et signaler l'erreur, plutôt que d'inventer une correspondance, car une erreur de sélecteur en cours d'enregistrement est coûteuse.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ssunduko/product-video/tree/HEAD/.claude/skills/resolve-selectors

Demander à votre IA préférée

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

Documentation

Résolution des sélecteurs en langage naturel

Un script .demo dit ce qu'il veut dire :

selectors:
  composer = ask "la boîte de message en bas du chat"

Votre travail consiste à trouver ce que cela représente réellement dans le DOM en direct et à l'écrire dans scripts/<nom>.selectors.json, afin que script.mjs puisse le compiler en un sélecteur ordinaire et que driver.mjs puisse enregistrer une prise déterministe.

Vous êtes le résolveur. Rien dans le pipeline n'appelle un modèle — script.mjs lit le fichier compagnon et refuse de compiler sans lui. La résolution a lieu ici, une fois, avant l'enregistrement, car le timing de la prise est la timeline vidéo et un aller-retour avec un modèle pendant une exécution créerait un temps mort dans la vidéo finale.

Avant de commencer

  • L'application doit être accessible et, si elle nécessite une connexion, déjà connectée dans le Chrome de l'utilisateur. C'est tout l'intérêt de l'extension : elle atteint la session réelle, donc pas de rituel SSO ni de code email à remplir.
  • Lisez d'abord le script. Vous avez besoin de l'en-tête app:/target: pour l'URL, et des beats, car les sélecteurs doivent être résolus dans l'ordre du flux (voir ci-dessous).

Procédure

  1. Obtenez la liste de travail.

    cd pipeline
    node script.mjs ../scripts/<nom>.demo --intents
    

    JSON sur stdout : chaque sélecteur ask, son intention et sa résolution actuelle (null si non résolu). Résolvez les null. Re-résolvez les autres seulement si l'utilisateur dit que le flux est cassé.

  2. Chargez les outils navigateur en UN SEUL appel ToolSearch, puis appelez tabs_context_mcp avant toute autre chose. Créez un nouvel onglet avec tabs_create_mcp sauf si l'utilisateur a pointé vers un existant.

  3. Parcourez le flux dans l'ordre des beats. C'est la partie facile à mal faire : beaucoup de sélecteurs n'existent pas sur la page d'accueil. Un tableau de résultats n'apparaît qu'après l'envoi d'une question ; un contrôle "Stop" n'existe que pendant la génération. Parcourez donc les beats du script, en résolvant chaque ask au moment où son élément est à l'écran.

    Données réelles. Avant toute étape qui crée, modifie, envoie ou supprime quoi que ce soit, arrêtez-vous et demandez à l'utilisateur. feature.demo envoie quatre messages à un compte Salesmessage réel. Survolez plutôt que de cliquer là où vous avez seulement besoin de localiser quelque chose, et ne cliquez jamais sur un contrôle destructeur pour "voir ce que c'est".

  4. Trouvez l'élément et choisissez la poignée la plus durable. Par ordre de préférence :

    PréférerPourquoi
    [data-testid=...], data-test, data-qaplacés là pour être sélectionnés ; survivent aux refontes
    un id stablebon sauf s'il semble généré (:r3a:, id-1a2b)
    bouton/lien par nom accessible exact → btn:Nomle btn: du pilote correspond au texte, aria-label et img[alt] interne
    [aria-label=...], [role=...]stable et généralement sémantique
    structure sémantique (main table, nav a[href="/equipes"])résiste aux changements de style

    N'utilisez jamais : les chaînes nth-child, les noms de classe générés (css-1a2b3c, longues piles Tailwind), ou quoi que ce soit basé sur du contenu généré. Ce dernier point est le piège que toute cette fonctionnalité vise à éviter — la réponse d'un modèle est formulée différemment à chaque exécution, donc un sélecteur correspondant à son texte est un pile ou face. Ancrez-vous sur le conteneur ou sur un signal d'achèvement à la place.

  5. Vérifiez avant d'écrire. Pour chaque candidat, confirmez avec javascript_tool qu'il correspond exactement à un élément et que cet élément est visible :

    const q = 'div[data-testid="chat-input"]';
    const n = document.querySelectorAll(q);
    console.log(JSON.stringify({
      q, count: n.length,
      visible: n[0] ? !!(n[0].offsetWidth || n[0].offsetHeight) : false,
      tag: n[0]?.tagName, editable: n[0]?.isContentEditable,
    }));
    

    Relisez-le avec read_console_messages. Plus d'une correspondance, ou zéro, signifie continuez à chercher — n'écrivez pas un sélecteur que vous n'avez pas vu correspondre.

  6. Écrivez le fichier compagnon, scripts/<nom>.selectors.json :

    {
      "resolvedAgainst": "https://claude.ai/new",
      "resolvedAt": "2026-08-10T09:00:00Z",
      "resolvedBy": "claude-in-chrome",
      "selectors": {
        "la boîte de message en bas du chat": {
          "spec": "div[data-testid=\\
    

Skills associés