サービスUIは、何よりもまずRun inspectorです。実行に対する新しい見方を導入するのではありません。Riderが実行中に追記し、CLIが出力するものとまったく同じJournalを描画します。表示されるDAG、手順の入力と出力、リトライ、リプレイボタンはすべて、1つの追記専用でcontent-addressedなログを読みます。2つ目の信頼できる情報源はありません。 このページ全体では、標準例としてdaily-price-watch Flowを使います。browser Tool search-price@1.2.0 が価格をスクレイピングし、transform手順が結果を整形し、条件付きのhttp.postがそれをシークレットWebhookへ送信します。

Journalがデータソースです

すべての実行は、Journalを持つRunを生成します。Journalは追記専用のイベントシンクで、各手順の状態遷移が1つのエントリーになります。インスペクターはそのログの読み取り役にすぎません。インスペクターが可視化する手順ライフサイクルを振り返ると、次のようになります。 各遷移は型付きのJournalエントリーです。インスペクターが読み取るエントリーは次のとおりです。
イベントインスペクターが描画するもの
run_startedflow_digestinputs_digestを含む実行ヘッダー
step_startedrunning状態に入るノードと、そのattempt番号
step_succeeded緑のノード。出力はoutput_digestで示される
step_failed赤のノード。マスクされたDomainErrorを伴う
step_skipped薄く表示されたノード。reasonを伴う
effect_recorded記録済みの外部効果。冪等性keyresult_digestでキー付けされる
run_finished終端状態: succeededfailed、またはcanceled
Journalは追記専用かつcontent-addressedで、すべての出力と効果がdigestで保存されます。そのため、再開、リプレイ、そしてインスペクター自体が可能になります。インスペクターは再計算しません。記録済みの事実を読み取ります。
出力と効果の結果はdigest単位で保存されます。大きな本文やバイナリ本文はblob storeに置かれ、Journalにはdigestだけが保持されます。インスペクターは、手順を開いたときに本文をオンデマンドでストリーミングします。サイズの大きすぎるペイロードは、インライン値ではなくartifact参照として表示されます。

TimelineとDAG

最初のビューはグラフです。インスペクターは、RiderがFlowSpecから導出したものと同じDAGをたどり、各ノードにJournalの状態を重ね合わせます。
  • どの手順が実行されたか - runningに到達してからsucceededになったノード。
  • どの手順がスキップされたか - when述語がfalseと評価されたノード。薄く表示され、記録済みのreasonを伴います。daily-price-watchでは、価格がしきい値を超えなかった日はhttp.postノードがスキップされます。
  • 何が並列に実行されたか - 並行にディスパッチされた独立手順は、並列トラックに表示されます。(並行性はmaxConcurrencyで上限が定められ、Launcherがその上限を選びます。)
  • どこに時間がかかったか - Timelineはエントリーをatタイムスタンプに沿って配置するため、遅いsearch-price browser手順がすぐに見えます。
グラフは表示用です。Journalは表示のために効果の全順序を記録しますが、リプレイと再開は厳密に手順IDと冪等性キーだけをキーにします。Journal上の位置は使いません。そのため、並行手順を異なる順序でコミットした2つの実行でも、同じ結果が表示され、同一にリプレイされます。Timelineが反映するのは壁時計時間だけで、セマンティクスではありません。
foreachを持つ手順はN個の子呼び出しへファンアウトし、インスペクターは各子を親の下に表示し、index順の配列へ集約します。

手順の詳細

ノードを選択すると、その手順のJournalエントリーから組み立てられた詳細が開きます。
  • 入力。シークレットはマスクされます。 入力は記録されたとおりに表示されます。そしてシークレットは式レイヤーを通過しないため(taint rule)、シークレット由来のバイト列は値ではなくプレースホルダー{secret:<slot>}としてJournalに記録されます。したがって、daily-price-watchのhttp.postに含まれるWebhook URLは、実際のエンドポイントではなく、マスクされたslotとして表示されます。RBACロールに関係なく、シークレットのがインスペクターで公開されることはありません。
  • 出力。 output_digestから描画されます(大きな本文はblob storeからストリーミングされます)。
  • リトライ。step_startedattempt番号を持つため、詳細には完全なリトライシーケンスと、それを制御したretryポリシーが表示されます。
  • 解決済みのToolバージョンとそのcontract digest。 詳細には、どのToolが実行されたか、つまりsearch-price@1.2.0と、それが解決されたcontract digestが正確に表示されます。これが、その実行を再現可能にする固定された同一性です。
手順が失敗した場合、インスペクターはそのDomainErrorを描画します。安定したcode(例: tool.browser.locator_missingまたはtool.http.timeout)、問題のstep、マスクされた入力、そしてretryableが表示されるため、シークレットを漏らさずに失敗へ対処できます。コードについては診断リファレンスを参照してください。

Live view - 実行中のRunを見る

事後的なJournalビューに加えて、ホスト型サービスはRunをまだ実行中の間に表示できます。GET /api/automations/:id/run-liveは、セッションCookie認証済みのWebSocketで、Runが現在操作しているブラウザータブのライブCDPスクリーンキャストを中継します。
1

RunがAPIプロセス上で開始する

POST /v1/run/:flow(または同期的なPOST /mcp Tool呼び出し)は、WebSocketルートを提供するものと同じサービスプロセス上でディスパッチされます。browser capabilityがスクリーンキャストをサポートしている場合、CDPフレームソースはRun IDではなくオートメーションのIDの下に登録されます。Run IDは、Runが(多くの場合すでに)完了するまで呼び出し元からは知ることができないためです。
2

Runの実行中にクライアントがソケットを開く

/api/automations/:id/run-liveはセッション認証とorg所有権(本番ではOrigin許可リストも)を確認し、そのオートメーションIDのソースを検索します。現在実行中のRunがない場合は{"type":"closed"}となり、ソケットは閉じます。クライアントは、Runが進行中だと分かっている間だけこれを開くことが期待されます。
3

フレームがJSONテキストメッセージとしてストリームされる

各スクリーンキャストフレームごとに{"type":"frame", seq, mime, data}が送られます(接続直後に最新のバッファ済みフレームが即座にflushされ、その後ライブフレームが続きます)。また、オープン時に一度だけ{"type":"state","state":"running"}が送られます。ソケットは読み取り専用で、クライアントが何かを送り返すことはありません。
4

Runが完了するとソースは破棄される

Runのfinallyブロックはhubからそのオートメーションのエントリーを削除するため、Run完了後も開いたままのソケットには、そのRunのフレームはそれ以上届きません。
Live viewが中継するのは同期ディスパッチ(JT_RUN_DISPATCH=sync、デフォルト)だけです。queue-dispatchされたRunは、ソケットを提供するAPIプロセスとメモリーを共有しない別のworkerプロセスまたはfleetで実行されるため、登録されるものがありません。scheduled/cron-triggeredなRunも同様です。発火時にソケットを開く呼び出し元が存在しないためです。同期的なPOST /mcp Tool呼び出しは、/v1/run/:flowが使うものと同じhubに登録されるため、MCPでトリガーされたRunはRESTやPlaygroundのRunとまったく同じように監視できます。queue-dispatchされたMCP呼び出しは監視できません。
これは、Build studioがオーサリング中に使う同じlive-view機構(/api/authoring/:id/live)の、Runスコープの別インスタンスです。同じwire format、同じthin-shim relay、同じ単一プロセスの注意点を持ちます。これはJournalを補完するもので、置き換えるものではありません。live viewはRunの実行にブラウザーを表示し、Journal(および上記のDOM replay)はRunが終わった後に検査するものです。

タイムトラベル

インスペクターでは、Journalエントリーを1つずつ進めながら、再開が行うのと同じ方法で各フレームのコンテキストを再構築できます。完了済みの手順は記録済みの出力を返し、記録済みの効果は記録済みの結果を返します。Runを不変の事実のシーケンスとして、前後にたどることができます。 browser Toolでは、タイムトラベルはさらに進みます。記録済みセッションのDOM replayをスクラブできます。browser Tool自体が決定論的であり(locatorを記録します)、その読み取りも記録されるため、インスペクターはsearch-price@1.2.0が何を見て何をしたかをフレームごとに再構築し、ドリフトしたスクレイピングを診断できます。
DOM replayは、記録済みのブラウザーセッションをJournalから読み取ります。ライブブラウザー呼び出しは行いません。browser Toolがどのようにセッションを決定論的に記録するかについては、ブラウザー自動化を参照してください。

Replay - 昇格前に検証する

最も強力なインスペクター操作はReplayです。UIから、Journalを元にFlowを再実行し、まだ同じように振る舞うことを表明できます。これはコマンドラインでbrowserflow replay <run-id> --verifyを実行するのと同じで、ボタンとして公開されています。
1

Runをfixtureとして選ぶ

既知の良好なdaily-price-watch Runを選びます。そのJournalは、flow_digest、すべての記録済み効果、そしてsearch-price@1.2.0のcontract digestを固定しています。
2

--verifyで密閉的にリプレイする

インスペクターは密閉的モードでリプレイします。注入されたnetclockrandomfs読み取り、browser capabilityは、すべてJournalだけを裏付けとして動作します。外部呼び出しは行われず、シークレットも不要です。 --verifyでは、インスペクターはすべての手順出力が記録済み出力と一致することを表明します。
3

昇格する、またはしない

search-priceをアップグレードしていて、verify replayがまだ一致するなら、振る舞いは変わっておらず、そのToolを昇格できます。差異があれば、--verifyは失敗し、どの手順の出力digestが変わったかを正確に示します。アップグレードがライブRunへ到達する前に分かります。
これはインスペクターに組み込まれた回帰テストです。Journalをfixtureとして固定すると、振る舞いを変えるToolアップグレードはverify replayで失敗します。
インスペクターからのReplayは密閉的です。何にも触れず、外部書き込みを再発火しません。別の--rerunモード(読み取りはリプレイするが、効果はライブで再実行するため、ライブシークレットが必要)は、意図的で明示的な選択肢であり、verifyと混同されることはありません。完全な違いについてはReplayを参照してください。

単一の信頼できる情報源 - UIとCLI

インスペクターは、CLIが読むものと同じJournalを読みます。「UIで見えるもの」と「browserflow inspectが出力するもの」は同じデータです。2つ目のstoreも、再導出されたビューも、コンソールだけの状態もありません。
# CLIはUIが描画するものと同一のJournalを読む
browserflow inspect <run-id>

# リプレイボタンは、このコマンドをUIで公開したもの
browserflow replay <run-id> --verify
これは、オーサリングでも成り立つ同じ不変条件です。UIキャンバスとYAMLは1つのFlowSpecの2つの面であり、digestがどのバージョンがliveかを全員に伝えます。可観測性はそれを継承します。Run inspectorとCLIが一致するのは、1つの追記専用ログを読むからであり、そのログに対する2つの見解を読むからではありません。
ロールは、誰がRunとそのJournalを読めるかをスコープしますが、ロールに関係なく、シークレットのがRun inspectorで公開されることはありません。マスクは記録時に行われます(シークレットは{secret:<slot>}プレースホルダーとしてJournalに記録されます)。そのため、インスペクターを通じてシークレット値を明かせるロールはありません。その値はJournal内にそもそも存在しません。
はい。各スケジュール実行はJournalを持つ通常のRunなので、失敗した、または実行されなかったスケジュールも、手動で開始したRunとまったく同じように検査およびリプレイできます。
Journalは追記専用なので、10手順中9手順目で中断されたRunにも、1から8までのエントリーは記録されています。インスペクターは完了したものを描画し、Runはそのfrontierから再開できます。手順1から8は再実行されません。

実行と再現性

Rider、手順ライフサイクル、Journalがすべての効果をどのように記録するか。

CLIリファレンス

browserflow inspectbrowserflow replay。同じデータをコマンドラインで扱います。

ブラウザー自動化

browser ToolがDOM replay用の決定論的セッションをどのように記録するか。

コントロールプレーン

Run inspectorが任意のサービス層のどこに位置するか。