replay-user-flows について
アプリの操作手順を flow として保存し、回帰チェックに再生する Reticle スキルです。セマンティックアンカーと宣言した結果を使い、クリックの再現にとどまらない検証を行います。
主な機能
- 01セッション操作を flow として自動保存
- 02flow の決定論的な再生
- 03変更ファイルに応じた flow 選択
- 04提案されたアンカー再設定で drift を修復
- 05アサーションのカバレッジ確認
活用シーン
- 01製品の主要な操作手順を回帰テスト
- 02コード変更の影響を受ける flow の再生
- 03結果をアサートしない保存済み flow の特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ reticlehq/ reticle --skill replay-user-flowsインストール後、Claude Code で/replay-user-flowsを入力して読み込まれたか確認します。
詳細
旅を一度記録すれば、いつまでも再検証できます
アプリを探索して旅を見つける作業に最もコストがかかります。モデルに同じ操作を再度させると、変更のたびにそのコストが発生します。Reticle のフローなら、一度だけで済みます。旅はセマンティックアンカーとともに保存され、その後は決定論的に再生されます。
プロジェクトに Reticle が組み込まれている必要があります。まだ設定していませんか?reticle スキルに従ってください。Reticle をインストールし、init によるアプリのファイル変更前にユーザーへ確認し、フローを1つ検証します。
記録
確認する必要はありません。セッションが終了すると操作がフローとして自動的に保存され、.reticle/flows/ に書き込まれます。コミットしてください。そうすれば、リポジトリ上のどのエージェントでも再生できます。
コミットする価値があるかどうかは、操作の進め方で決まります。ステップに結果が保持されるのは、結果を宣言した場合だけです。そのため、次のようにゴールデンパスを操作してください。
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "signal", name: "task:created" } })
このステップはテストとして再生されます。何も検証しない reticle_act だけでは、クリックが証明なしで保存され、どのようなリグレッションがあっても成功として再生されます。
自動で付けられる名前ではなく、意図的にフローに名前を付けるには、reticle_record と reticle_flow_save を reticle_run { tool, args } 経由で実行します。どちらも告知されておらず、告知する必要もありません。reticle_run はデフォルトのサーフェスにあり、名前を指定すれば登録済みの任意のツールを呼び出せます。RETICLE_ADVERTISE_ALL_TOOLS=1 を設定すると、以前の未マージのツール名で、これらが明示的に告知されます。エージェントには設定しないでください。このスキル内の呼び出しではデフォルトの名前を使います。
クリックだけでなく、ビジネス上の成果を注釈として付けて、再生によって旅が何かを 達成した と証明できるようにしてください。上記2つのような拡張サーフェスを使います。
reticle_run({ tool: "reticle_annotate", sessionId, args: { flow: "create-task", kind: "intent", text: "create a task and see it in the list" } })
reticle_run({ tool: "reticle_annotate", sessionId, args: { flow: "create-task", kind: "success-state", signal: "task:created" } })
最初に data-testid を追加する必要はありません。 要素に testid がないステップは、コンポーネントとソースの位置を自動的にアンカーとして使用します。また、testid を保持するリファクタリングなら、成功として再生されます。
再生
reticle_verify({ sessionId, action: "change", files: ["src/tasks/TaskList.tsx"] })
これにより、それらのファイルを対象とするフローが再生されます。名前を指定したフローを直接再生するには、reticle_run 経由で reticle_flow_replay を呼び出します。
ステータスは3種類で、失敗の内容は一目で分かります。
| ステータス | 意味 | 次の対応 |
|---|---|---|
ok | すべてのアンカーが解決され、すべての期待結果が成立しました | 完了 |
drift | アンカーが見つかりませんでした。名前が変更された testid や、発火しなかったシグナルなどが原因です | decision.nextAction を確認してください。ファイル名と行番号、および最も近い位置に残っているアンカーが示されます |
error | フローファイルがないか無効であるか、実行時にステップが失敗しました | エラーエンベロープの失敗したステップをもとに修正してください |
ドリフトが発生した場合、reticle_verify { action: "heal" } は最も近い一致候補への再バインドを提案し、フローが古くなるのを防ぎます。名前の変更が意図的だった場合は適用してください。意図的でなかった場合は、問題の発見として扱ってください。
変更のたびにスイート全体を再検証する
reticle_verify({ sessionId, action: "flows" })
// → { status, total, passed, failed, failures: [{ flow, verdict, whatChanged, whereInSource, nextAction }] }
1回の呼び出しで、保存済みのすべてのフローを対象にでき、フローごとにモデルを使う必要はありません。詳細が表示されるのは失敗した場合だけなので、成功したスイートの確認にはほとんどコストがかかりません。ビルド → reticle_verify { action: "flows" } → 各 nextAction に従って修正 → 繰り返す、というのがリグレッションループです。そもそも記録する目的はこれです。
変更によって失敗する可能性のあるフローだけを再生する
大規模なスイートでは、1つのファイルを編集した後にすべてを再生するのは無駄です。差分を渡してください。
reticle_verify({ sessionId, action: "change", since: "HEAD~1" })
編集したファイルを対象とする保存済みフローを特定し、それだけを再生します。git ref またはファイル一覧を渡してください。内側のループではこちらを使い、リリース前には reticle_verify { action: "flows" } を実行してください。対象を絞った確認は高速で、全体確認は保証になります。
実際に何かを証明するフローはどれか
reticle_run({ tool: "reticle_domain", sessionId }) // not advertised, one hop away
// → { flowCount, coverage: { asserted, presenceOnly, assertionFree }, gaps: { declaredUntestedSignals, … } }
何もアサートしない記録済みフローは、どのようなリグレッションがあっても成功として再生されます。証明できるのはクリックが引き続き解決されることだけで、アプリが引き続き動作することではありません。記録セッション後にこれを確認してください。assertionFree に入っているものはすべて、success-state を指定して annotate する必要があります。そうしなければ、単なる飾りです。
記録しない場合
一度だけ実行するジャーニーなら、reticle_act_and_wait で操作して、そのまま忘れるほうが手間がかかりません。プロダクトを定義するフロー(回帰が起きると困るもの)を記録し、探索的な操作は保存せずに残しておきます。中途半端なフローを40個集めても、得られる価値より注意を払う負担のほうが大きくなります。
誠実さ
リプレイでは、実際に起きたことが報告されます。drift は合格ではありません。また、アプリが実際に壊れたときにフローを修復して合格に見せることは、スイート全体を無価値にする唯一の行為です。名前の変更が意図したものでなければ、drift こそが発見事項です。whereInSource ポインターとともに報告してください。
フローの完全なリファレンス(1ページ):curl https://docs.reticle.sh/flows.md。すべてのインデックス:curl https://docs.reticle.sh/llms.txt。