Communitygithub.com

ssunduko/product-video

パイプラインの`.demo`スクリプト内の自然言語`ask "..."`セレクタを、ライブアプリに対してChrome拡張機能「Claude in Chrome」を使って解決し、`<script>.selectors.json`サイドカーファイルを書き込みます。スクリプトに未解決のインテントがある場合、コンパイルやレコーディングが「selector(s) still state an intent」というエラーで失敗する場合、またはリデザインにより以前動作していたセレクタが壊れた場合に使用します。

product-video とは?

このスキルは、パイプラインの`.demo`スクリプト内で使用される自然言語セレクタ(`ask "..."`)を、ライブアプリケーションの実際のDOM要素に解決し、その結果をサイドカーファイル(`.selectors.json`)として保存するためのものです。主にClaude CodeやCursorなどのAIエージェント開発フレームワークで使用され、ビデオテイクの録画前にセレクタを確定させることで、録画中のモデル呼び出しによるタイミングの不確実性を排除します。対象プラットフォームはChromeブラウザ上の任意のWebアプリケーションで、Claude in Chrome拡張機能を介してユーザーの実際のセッションにアクセスします。スキルでは、スクリプトのビート順に従いページフローを段階的に進めながら、各セレクタが画面上に現れた瞬間に解決する「フロー順解決」を採用しています。また、`data-testid`や`aria-label`など、リデザインに強い安定したセレクタの優先順位付けを行い、生成されたクラス名やnth-childチェーンなどの脆弱なセレクタを避けるよう指示しています。解決が不可能な場合は、誤ったセレクタを発明せず、エラーを報告して停止する安全策も含まれています。

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

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

自然言語セレクタの解決

.demo スクリプトは、その意図を明確に記述します:

selectors:
  composer = ask "チャット下部にあるメッセージボックス"

あなたの仕事は、それが実際のDOM内で何であるかを特定し、その結果を scripts/<name>.selectors.json に書き込むことです。これにより、script.mjs がそれを通常のセレクタにコンパイルし、driver.mjs が決定論的なテイクを録画できるようになります。

あなたがリゾルバーです。 パイプライン内のどの処理もモデルを呼び出しません。script.mjs はサイドカーファイルを読み取り、それがなければコンパイルを拒否します。解決は録画前に一度だけ行われます。なぜなら、テイクのタイミングはビデオのタイムラインであり、実行中にモデルの往復が発生すると、完成したビデオに無音・無映像の空白が生じてしまうからです。

開始前の準備

  • アプリにアクセス可能であり、ログインが必要な場合は、ユーザーのChromeで既にサインインしている必要があります。これが拡張機能を使用するポイントです:実際のセッションにアクセスするため、SSOの儀式やメールコードの入力は不要です。
  • 最初にスクリプトを読んでください。URLのための app:/target: ヘッダーとビートが必要です。なぜなら、セレクタはフロー順に解決する必要があるからです(後述)。

手順

  1. 作業リストを取得します。

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

    標準出力にJSONが出力されます:すべてのaskセレクタ、そのインテント、および現在の解決状態(未解決の場合はnull)。nullのものを解決してください。ユーザーがフローが壊れていると言わない限り、残りのものは再解決しないでください。

  2. ブラウザツールを1回のToolSearch呼び出しでロードし、その後、他のすべてに先立って tabs_context_mcp を呼び出します。ユーザーが既存のタブを指定しない限り、tabs_create_mcp で新しいタブを作成します。

  3. フローをビート順にたどります。 これは間違いやすい部分です:多くのセレクタはランディングページには存在しません。結果テーブルは質問が送信された後にのみ表示されます。「停止」コントロールは何かが生成されている間だけ存在します。そのため、スクリプトのビートを順に実行し、各askの要素が画面に表示された瞬間に解決します。

    ライブデータ。 何かを作成、変更、送信、削除するステップの前には必ず停止してユーザーに確認してください。feature.demo は実際のSalesmessageアカウントに4つのメッセージを送信します。クリックではなくホバーを使用して要素を特定するだけにし、破壊的なコントロールを「それが何かを見るため」にクリックしないでください。

  4. 要素を見つけ、最も耐久性のあるハンドルを選択します。 優先順位は以下の通りです:

    優先理由
    [data-testid=...]、data-test、data-qa選択されるために配置されており、リデザインにも耐えます
    安定した id生成されたように見えない限り有効(:r3a:、id-1a2b など)
    正確なアクセシブル名によるボタン/リンク → btn:Nameドライバの btn: はテキスト、aria-label、内部の img[alt] にマッチします
    [aria-label=...]、[role=...]安定しており、通常はセマンティックです
    セマンティック構造(main table、nav a[href="/teams"])スタイル変更に耐えます

    決して使用しないでください: nth-childチェーン、生成されたクラス名(css-1a2b3c、長いTailwindスタック)、または生成されたコンテンツに基づくもの。最後のものは、この機能全体が避けようとしている落とし穴です。モデルの回答は実行ごとに異なる表現になるため、そのテキストに一致するセレクタはコインフリップです。代わりに、コンテナまたは完了シグナルにアンカーしてください。

  5. 書き込む前に検証します。 各候補について、javascript_tool を使用して、それが正確に1つの要素にマッチし、その要素が可視であることを確認します:

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

    read_console_messages で結果を読み取ります。複数のマッチ、または0件のマッチは、さらに探し続ける必要があることを意味します。マッチを確認していないセレクタを書き込まないでください。

  6. サイドカーファイル scripts/<name>.selectors.json を書き込みます:

    {
      "resolvedAgainst": "https://claude.ai/new",
      "resolvedAt": "2026-08-10T09:00:00Z",
      "resolvedBy": "claude-in-chrome",
      "selectors": {
        "チャット下部にあるメッセージボックス": {
          "spec": "div[data-testid=\"chat-input\"]",
          "evidence": "contenteditable tiptap div, aria-label 'メッセージを書く', 1個マッチ、可視"
        }
      }
    }
    

    キーはインテントテキスト、スクリプトからそのままコピーしたものです。セレクタの名前変更やブロックの並べ替えによって解決が孤立してはいけません。spec はドライバが受け入れる任意の形式です:生のpuppeteerセレクタ、btn:テキスト|代替テキスト、または ::-p-text(部分文字列) など。evidence は実際に観察した内容です。後で他の人がそれがまだ有効かどうかを判断できるように記述してください。

  7. 確認して引き継ぎます。

    node script.mjs ../scripts/<name>.demo --intents   # 未解決が0であることを確認
    node script.mjs ../scripts/<name>.demo --print     # コンパイル
    

    解決した内容、どの候補の間で推測する必要があったか、および破壊的なステップが必要なためスキップしたものを報告してください。

解決できない場合

その旨を伝えて停止してください。セレクタをでっち上げないでください。未解決のインテントは、Chromeが起動する前にきれいなコンパイルエラーとなります。間違ったセレクタは、録画開始後のテイク途中で失敗します。これはコストのかかる失敗の場所です。説明に等しく一致する2つの要素がある場合は、自分で選ぶのではなく、ユーザーにどちらを意図しているか尋ねてください。

注意点

症状原因 / 修正
要素がページに存在しないフローの後半に現れます。ビートを順にたどり、各インテントが実際に画面に表示された時点で解決してください
2つの要素がマッチする説明が曖昧です。ユーザーと絞り込み、スクリプト内の ask も言い換えて、次回の解決が曖昧にならないようにしてください
セレクタは今動作するが、次回の実行で壊れる生成されたコンテンツまたは生成されたクラスに基づいています。testid、role、またはコンテナに再アンカーしてください
wait ... gone アンカーこれらは本質的に一時的なものです(生成中の停止ボタンなど)。画面上にある間に解決し、aria-label を優先してください。テキストよりも変更が少ないです
リデザイン後に解決がずれたサイドカーファイルからそのキーだけを削除し、再実行してください。.demo は変更されません。それがポイントです
ダイアログが拡張機能をブロックするconfirm/alert を開くようなものをクリックしないでください。モーダルダイアログは手動で閉じられるまで拡張機能をフリーズします

関連スキル