Communitygithub.com

ssunduko/product-video

Löse die natürlichsprachlichen `ask "..."`-Selektoren in einem `.demo`-Pipeline-Skript gegen die Live-App auf, unter Verwendung der Claude in Chrome-Erweiterung, und schreibe die `<script>.selectors.json`-Sidecar-Datei. Verwende dies, wenn ein Skript unaufgelöste Intents hat, wenn die Kompilierung oder Aufzeichnung mit „Selektor(en) geben noch einen Intent an“ fehlschlägt, oder wenn ein Redesign Selektoren beschädigt hat, die zuvor funktionierten.

Was ist product-video?

Diese Fähigkeit ist speziell für den Umgang mit `.demo`-Pipeline-Skripten von AI-Agenten (wie Claude Code, Cursor oder Codex) konzipiert. Ihre Hauptaufgabe ist es, natürlichsprachliche Selektoren (definiert als `ask "..."`-Intents in der YAML-Datei) aufzulösen, indem sie die Live-Webanwendung im Browser des Benutzers inspiziert. Dies wird erreicht, indem die `Claude in Chrome`-Erweiterung als Brücke zur realen Sitzung des Benutzers genutzt wird, sodass keine Anmeldeprozesse oder Authentifizierungslasten nötig sind. Der Vorteil dieser Methode gegenüber der Laufzeitauswertung ist, dass die Auflösung einmalig vor der Videoaufzeichnung erfolgt; so wird verhindert, dass Modell-Latenzen die Aufnahme unterbrechen oder zu „toter Luft“ im fertigen Video führen. Der Skill arbeitet mit einem klaren, manuellen Verfahren: Er listet alle ausstehenden Intents auf, durchläuft das Skript Beat für Beat in der richtigen Reihenfolge (da Selektoren oft erst später im Flow erscheinen), identifiziert robuste DOM-Selektoren und schreibt die Ergebnisse in die Sidecar-Datei. Die Plattformunterstützung umfasst die Chrome-Erweiterung und Befehlszeilentools wie `script.mjs`. Die Anleitung betont die Bedeutung von beständigen Selektoren (z. B. `data-testid` oder `aria-label`) und warnt vor generierten Klassen oder inhaltsbasierten Selektoren.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Auflösung natürlichsprachlicher Selektoren

Ein .demo-Skript sagt, was es bedeutet:

selectors:
  composer = ask "das Nachrichtenfeld unten im Chat"

Ihre Aufgabe ist es, herauszufinden, was das tatsächlich im Live-DOM ist, und es in scripts/<name>.selectors.json zu schreiben, damit script.mjs es in einen gewöhnlichen Selector kompilieren und driver.mjs eine deterministische Aufnahme machen kann.

Sie sind der Resolver. Nichts in der Pipeline ruft ein Modell auf – script.mjs liest die Sidecar-Datei und weigert sich, ohne sie zu kompilieren. Die Auflösung erfolgt hier, einmalig, vor der Aufzeichnung, weil das Timing der Aufnahme die Video-Zeitleiste ist und eine Modell-Roundtrip während eines Laufs zu toter Luft im fertigen Video führen würde.

Bevor Sie beginnen

  • Die App muss erreichbar sein und, falls ein Login erforderlich ist, bereits angemeldet im Chrome des Benutzers. Das ist der Sinn der Erweiterung: Sie greift auf die echte Sitzung zu, also gibt es kein SSO-Ritual und keinen E-Mail-Code zum Ausfüllen.
  • Lesen Sie zuerst das Skript. Sie benötigen den app:/target:-Header für die URL und die Beats, weil Selektoren in der Reihenfolge des Ablaufs aufgelöst werden müssen (siehe unten).

Vorgehen

  1. Holen Sie die Arbeitsliste.

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

    JSON auf stdout: jeder ask-Selector, sein Intent und seine aktuelle Auflösung (null, falls ungelöst). Lösen Sie die Null-Einträge auf. Lösen Sie den Rest nur dann erneut auf, wenn der Benutzer sagt, dass der Ablauf beschädigt ist.

  2. Laden Sie die Browser-Tools in EINEM ToolSearch-Aufruf, rufen Sie dann tabs_context_mcp auf, bevor Sie etwas anderes tun. Erstellen Sie einen neuen Tab mit tabs_create_mcp, es sei denn, der Benutzer hat auf einen vorhandenen verwiesen.

  3. Gehen Sie den Ablauf in der Beat-Reihenfolge durch. Dies ist der Teil, der leicht falsch gemacht wird: Viele Selektoren existieren nicht auf der Startseite. Eine Ergebnistabelle erscheint erst, nachdem eine Frage gesendet wurde; ein „Stop“-Steuerelement existiert nur, während etwas generiert wird. Gehen Sie also die Beats des Skripts Schritt für Schritt durch und lösen Sie jeden ask in dem Moment auf, in dem sein Element auf dem Bildschirm ist.

    Live-Daten. Bevor Sie einen Schritt ausführen, der etwas erstellt, ändert, sendet oder löscht, halten Sie inne und fragen Sie den Benutzer. feature.demo sendet vier Nachrichten an ein echtes Salesmessage-Konto. Fahren Sie mit der Maus, anstatt zu klicken, wenn Sie nur etwas lokalisieren müssen, und klicken Sie niemals auf ein destruktives Steuerelement, um „zu sehen, was es ist“.

  4. Finden Sie das Element und wählen Sie den haltbarsten Griff. In der Reihenfolge der Präferenz:

    BevorzugtWarum
    [data-testid=...], data-test, data-qadort platziert, um ausgewählt zu werden; überlebt Redesigns
    eine stabile idgut, es sei denn, sie sieht generiert aus (:r3a:, id-1a2b)
    Button/Link nach exaktem accessible-name → btn:Nameder Treiber btn: matcht Text, aria-label und inneres img[alt]
    [aria-label=...], [role=...]stabil und in der Regel semantisch
    semantische Struktur (main table, nav a[href="/teams"])überlebt Styling-Änderungen

    Verwenden Sie niemals: nth-child-Ketten, generierte Klassennamen (css-1a2b3c, lange Tailwind-Stapel) oder irgendetwas, das auf generierten Inhalt angewiesen ist. Letzteres ist die Falle, die diese ganze Funktion vermeiden soll – eine Modellantwort wird bei jedem Durchlauf anders formuliert, sodass ein Selektor, der auf ihren Text matcht, ein Glücksspiel ist. Verankern Sie sich stattdessen am Container oder an einem Abschlusssignal.

  5. Überprüfen Sie, bevor Sie es schreiben. Bestätigen Sie für jeden Kandidaten mit javascript_tool, dass er exakt ein Element matcht und dass das Element sichtbar ist:

    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,
    }));
    

    Lesen Sie es mit read_console_messages zurück. Mehr als ein Treffer oder null bedeutet, dass Sie weitersuchen müssen – schreiben Sie keinen Selektor, den Sie nicht match gesehen haben.

  6. Schreiben Sie die Sidecar-Datei, scripts/<name>.selectors.json:

    {
      "resolvedAgainst": "https://claude.ai/new",
      "resolvedAt": "2026-08-10T09:00:00Z",
      "resolvedBy": "claude-in-chrome",
      "selectors": {
        "das Nachrichtenfeld unten im Chat": {
          "spec": "div[data-testid=\"chat-input\"]",
          "evidence": "contenteditable tiptap div, aria-label 'Schreibe eine Nachricht', 1 Treffer, sichtbar"
        }
      }
    }
    

    Schlüssel nach dem Intent-Text, wortwörtlich aus dem Skript – eine Umbenennung eines Selektors oder eine Neuanordnung des Blocks darf keine Auflösung verwaist lassen. spec ist, was auch immer der Treiber akzeptiert: ein roher Puppeteer-Selektor, btn:Text|Alt oder ::-p-text(Teilstring). evidence ist das, was Sie tatsächlich beobachtet haben; schreiben Sie es so, dass die nächste Person erkennen kann, ob es noch gültig ist.

  7. Bestätigen und zurückgeben.

    node script.mjs ../scripts/<name>.demo --intents   # erwarte 0 ungelöste
    node script.mjs ../scripts/<name>.demo --print     # kompiliert
    

    Berichten Sie, was Sie aufgelöst haben, worüber Sie raten mussten und was Sie übersprungen haben, weil es einen destruktiven Schritt erforderte.

Wenn Sie einen nicht auflösen können

Sagen Sie es und stoppen Sie; erfinden Sie keinen Selektor. Ein ungelöster Intent ist ein sauberer Kompilierungsfehler, bevor Chrome überhaupt gestartet wird. Ein falscher Intent führt mitten in der Aufnahme zu einem Fehler – der teure Ort für einen Fehler. Wenn zwei Elemente gleich gut auf die Beschreibung passen, fragen Sie den Benutzer, welches gemeint war,

anstatt zu raten.

Fallstricke

SymptomUrsache / Lösung
Das Element ist nicht auf der SeiteEs erscheint später im Ablauf. Gehen Sie die Beats in der richtigen Reihenfolge durch; lösen Sie jeden Intent auf, wenn sein Element tatsächlich auf dem Bildschirm ist
Zwei Elemente passenDie Beschreibung ist mehrdeutig. Engen Sie sie mit dem Benutzer ein und formulieren Sie dann auch den ask im Skript um, damit die nächste Auflösung eindeutig ist
Selektor funktioniert jetzt, bricht beim nächsten DurchlaufEr ist auf generierten Inhalt oder eine generierte Klasse angewiesen. Verankern Sie ihn neu an einer Testid, einer Rolle oder einem Container
Ein wait ... gone-AnkerDiese sind von Natur aus flüchtig (z. B. ein Stop-Button während der Generierung). Lösen Sie ihn auf, während er auf dem Bildschirm ist, und bevorzugen Sie aria-label – es ändert sich weniger als der Text
Auflösung nach einem Redesign verschobenLöschen Sie nur diesen Schlüssel aus der Sidecar-Datei und führen Sie sie erneut aus. Das .demo ändert sich nicht; das ist der Sinn
Dialog blockiert die ErweiterungKlicken Sie nicht auf Dinge, die confirm/alert öffnen. Ein modaler Dialog friert die Erweiterung ein, bis er manuell geschlossen wird

Verwandte Skills