English · 日本語
Web UI(serve のブラウザアプリ)¶
bajutsu serveで開くブラウザ UI について、各タブが何をするか、どう操作するかをタスク指向で 説明します。起動フラグ、認証、ホスティングの詳細はこのページでは扱わず、 CLI リファレンス と self-hosting に委ねます。ここで扱うのは 画面であって、コマンドラインではありません。実装:
bajutsu/serve/(stdlib のサーバ)。マークアップはbajutsu/templates/serve.html.j2にあります。
関連: CLI リファレンス · scenarios · recording · reporting · selectors · configuration · self-hosting
Web UI とは何か、いつ使うか¶
Web UI は Tier 1 の利便性のための機能です。手で実行する CLI コマンドを、そのままブラウザから使える
フロントエンドにしたものです。CI(継続的インテグレーション)ゲートには含まれません。決定的な run の判定が
これに依存することはなく、ここで合否を下すものは何もありません。自然言語のゴールからシナリオを
オーサリングする、シナリオを実行してレポートを読む、アプリを探索して画面マップが描かれていく
様子を見る、実際のスクリーンショットに対してシナリオを編集する、run 履歴を俯瞰する。これらを
1 つのアクティブな config に対して、ターミナルのコマンドを切り替えることなく行えます。
UI の操作の多くは CLI コマンド(record、run、crawl、stats、lint)に対応します。例外は
Author タブで、その Capture / Edit / Enrich はシナリオファイルの作成と編集を助ける serve 専用の
機能で、対応する CLI コマンドはありません。ここでの説明でオプションの全体像が必要になったら、
CLI リファレンス が拠り所です。
起動する¶
リポジトリの checkout では、make serve でサーバを起動してください。これが一番手数の少ない方法です。
make serve(scripts/serve.sh)は、
設定した backend のオンデマンド依存を用意してからサーバを起動します。macOS では、ターゲットが XCUITest を
必要とするとき、バンドル済みの iOS Simulator ランナーが無いか古ければ make runner-bundle(Xcode の
xcodebuild と xcodegen でビルドします)でも用意します。これが無いと、iOS の実行は
no available actuator で失敗します。フラグは ARGS で渡します。
make serve # 既定ポート(8765)
make serve ARGS="--config demos/showcase/showcase.config.yaml --port 8766" # ショーケースアプリ
リポジトリにはルートの bajutsu.config.yaml が無いため、ショーケースアプリにはこの config 指定が
必要です。
make serve は内部で python -m bajutsu serve、すなわち CLI リファレンス が説明する
bajutsu serve コマンドを実行します。checkout の外で Bajutsu を導入した場合(make が無い場合)は、
bajutsu serve(または python -m bajutsu serve)を直接実行してください。その場合、backend の依存は
自分で用意します。iOS ターゲットには XCUITest ランナー(と Xcode)が要りますが、web(Playwright)
ターゲットには不要です。いずれの方法でも、サーバがブラウザを自動で開くことはありません。127.0.0.1 に
bind するので、起動したら表示された URL(既定は http://127.0.0.1:8765、--port を渡した場合はその
ポート)を自分で開いてください。よく使うフラグ(--port、--config、--root、--runs、
--baselines、--themes、--host、--token、--max-concurrent-runs、--evidence-store)は
ここまでの用途をカバーします。オプションの一覧は CLI リファレンス にあります。
画面の全体像¶
ヘッダには 9 つのトップレベルタブがあります。Record、Replay、Crawl、Author、
Stats、Flaky、Usage、Coverage、そして Trash(ソフトデリートした run が並び、
保持期間内なら復元できます。Trashを参照してください)
です。10 番目の Comparison は、bind している config が
target を 2 つ以上宣言しているときだけ現れます。target
どうしを比較するタブだからです(target を比較するを
参照してください)。タブの名前は表示する内容から採っています。同じサーバが /metrics で公開する
Prometheus 向けのエンドポイントは別物です。
その右に Open config(config を bind すると隣にその名前が出ます)と、
それを確認するための View ボタン(後述)、Settings、そして既定でシステム設定に追従するテーマ
ピッカーがあります。GitHub でサインインするデプロイでは、config 名の隣の小さなバッジが、この
セッションがどの org として振る舞っているかを示します。実行できる target、見える run と証跡、
secret まで、すべてのタブがこの org にスコープされるので、ひと目で読めることに
意味があります。複数の org を管理する admin なら、なおさらです。カーソルを重ねると login も出ます。
ローカルや共有トークンの serve にはサインインした identity もテナントも無いため、このバッジは
現れません。
GitHub 上のメンバーシップが複数の org へのアクセスを許すときは、このバッジがドロップダウンになります。 別の org を選ぶとページが再読み込みされ、その org として振る舞います。見えるものはそのテナントの run、 証跡、secret に変わり、権限もそのテナントが与えるロールになります。直前の org で持っていた ロールとは異なる場合があります。選択は保持されます。次回のサインインでは、あらためて決め直されることなく、 自分が選んだ org に着地します。保持されなくなるのは、その org が自分を受け入れなくなったときだけです。 そのときは次回のサインインで、残った候補のうちもっとも順位の高い org へ移ります。デプロイの admin Team のメンバーである admin は、そのデプロイが持つどの org としても振る舞えます。サインイン後に作られた org も 含みます。切り替えても、すでに済んだ作業は動きません。run は開始した org のものであり続け、その証跡と監査 エントリも同じです。
各タブはそれぞれ独立した 1 画面で、タブを切り替えても別のタブの作業内容は失われません。
一部のフォームは backend によって変わります。iOS の Simulator(XCUITest)では Device のピッカー、 Simulators の複数選択、erase device first が現れ、web ターゲット(Playwright / Chromium)では それらの代わりに show browser (headed) が現れます。それ以外は backend をまたいで共通です。 Replay タブには過去の run を並べる History の一覧もあります(後述)。
テーマ。 ヘッダのピッカーで見た目のテーマを選びます。登録済みのテーマがすべて並びます。組み込みの
Midnight(ダーク)と Daylight(ライト)に加え、--themes でドロップインしたテーマ(CLI リファレンス
を参照)も、ダークとライトに分けて並びます。自分で選ぶまでは OS の設定(または config の ui.default_theme)に
追従し、明示的に選ぶとその選択が(ブラウザのローカルストレージに)記憶されます。その後 OS 側の設定が変わると、
手動の上書きは破棄され、あらためてシステムのモードに追従します。
テーマは UI の動き、つまりビューやモーダル、パネルが切り替わるときのアニメーションも定義します。画面遷移は
作り込みで固定されたものではなく、テーマの一部です。ビューの切り替え、モーダルの開閉、タイル状ペインの再構成に
ついて、その時間、イージング、開始と終了のアニメーションを、テーマが --motion-* トークンで決めます(色トークンと
同じく serve.themes.css に説明があります)。動きのトークンを何も設定しないテーマは、組み込みのアニメーションを
そのまま使います。開始と終了のトークンを none にしたテーマは、その遷移を即座に描画します。
OS のアクセシビリティ 設定で「動きを減らす(reduce motion)」が有効なときは、すべての動きが即座の切り替えに変わるので、利用者の意向に 反してアニメーションすることはありません。run はこの設定を有効にした状態でブラウザを操作するため、アニメーションが 決定的な run に影響することもありません。
テーマエディタ。 ピッカーの横にある Edit ボタンをクリックすると、UI 内のテーマエディタが開きます。 エディタはトークン契約からフォームを自動生成します。上部に name(名前)と kind(ダーク/ライト)が並び、 続いて色トークンごとにネイティブのカラースウォッチ、モーショントークンごとにテキストフィールドが並びます。編集内容は ライブプレビューとしてそのまま反映され、ページのリロードは不要です。エディタからは次の操作ができます。
- Save to Local Draft:編集中のテーマをブラウザのローカルストレージに保存し、ヘッダーのピッカーに custom として即座に追加して選択状態にします。ページを再読み込みしても残りますが、ブラウザ固有の保存であり、ほかの serve セッションとは共有されません。エディタを開き直すと、この下書きから編集を再開できます。
- Upload to Server:テーマを
--themesディレクトリに書き込み、ドロップインとして登録します。その serve インスタンスのセッション間で共有され、次回の読み込みでピッカーに並びます。テーマの id は名前からサーバー側で決まります。 このボタンは、インスタンスを--themes付きで起動したときにだけ表示されます。テーマディレクトリがなければ、書き込む 先がないためです。 - Export:編集したテーマを
<name>-theme.cssとしてダウンロードします。--themesが受け付けるドロップイン 形式と同じなので、ローカルで作成したテーマをリポジトリにコミットして共有できます。 - Import:エクスポート済み(または手書き)の
.cssファイルを読み込んでフォームに反映します。ファイル内に フォームフィールドに対応しないトークンがある場合は、無視せずステータスメッセージで通知します。
パネル操作(デスクトップ)。 デスクトップ幅のウィンドウでは、Record、Replay、Crawl の各タブが パネルをタイル状に並べます。二つのパネルのあいだの区切りをドラッグすると、その二枚だけで幅を 再配分します(ほかのパネルの取り分は変わりません)。パネルの ⠿ グリップを別のパネルへドラッグ すると、中央に落とせば入れ替え、端に落とせばその側に分割して並べます。ビューごとのレイアウトは ブラウザのローカルストレージに保存されます。Record の run 結果ペインは、run の開始と閉じる操作に 合わせてこのタイルに加わり、また抜けます。
狭いウィンドウ。 スマートフォン幅ではタイルレイアウトの代わりに 1 列のスタックになり、各ビューに 小さな切替が付いて、一度に一つのペイン(フォーム、ログ、レポートなど)を全幅で表示します。失われる 機能はなく、配置だけが変わります。
Claude に到達できないとき。 Record と Crawl は AI provider を必要とします(Settings を参照)。Claude に到達できないあいだ(キーが無い、CLI がサインインしていない)、この二つのタブは 無効表示になり、開始ボタンはグレーアウトし、何が足りないかを名指しするバナーが Open Settings への ショートカットとともに出ます。provider を設定すると即座に解除されます。それ以外(Replay、Author、 Stats、Flaky、Usage、Coverage)は AI の設定なしで動きます。
アクティブな config を選ぶ¶
すべてのタブは 1 つのアクティブな config に対して動きます。Open config を押して bind します。 ダイアログには 3 つのソースがあります。
- From a Git repository。
github:owner/repo@ref:path/to/bajutsu.config.yamlの形で spec を 入力し、Load を押します。refはブランチ、タグ、またはコミット SHA です(既定はリポジトリの デフォルトブランチ)。部分木ごと取得するので、config のシナリオやビルド済みアプリも一緒に来ます。 - Upload a bundle (.zip)。 Choose a .zip… を押す(またはボックスにファイルをドロップする)と、
ホストのファイルシステムに触れないまま、自分のスイートをホスト型のサーバへ持ち込めます。zip の中身は
動くローカル checkout そのもの、つまり
bajutsu.config.yaml、そのscenariosツリー、config のappPathが指すビルド済みアプリバイナリです。秘匿情報は運びません。${secrets.*}はサーバの環境から 解決されます。 - or browse the server。 サーバの
--root配下に限定されたファイルブラウザで、ローカルの.yml/.yamlの config を選びます。リモートの利用者はホストのファイルシステムと関係を持たないため、 ホスト型のデプロイではこのソースは隠れます。
各ソースの詳しい挙動(content-addressed な Git キャッシュ、バンドルのサンドボックス化と zip-slip 対策、
--root への封じ込め)は CLI リファレンス に書いてあります。bind できる config は同時に
1 つだけで、別の config を開くと置き換わります。
バインドしている config を確認する¶
config 名の隣の View を押すと、タブが実際に動かしている config を確認できます。ダイアログは最初に
Structured ビューで開きます。折りたたみ可能な key-value のツリーで、入れ子になったオブジェクトやリストは
それぞれトグルになっており、必要なところだけ展開できます。Raw に切り替えると、コメントも含めた生の YAML
が表示されます。どちらのビューの上にも config のパスが出て、Git リポジトリから取得したものであれば取得元
(リポジトリ、指定した ref、解決されたコミット SHA)も表示されます。これが効くのは Git ソースのときです。
Git ソースのアクティブなパスは content-addressed なキャッシュ上の不透明な場所
(…/gitsrc/<host>/<owner>/<repo>/<sha>/…)になるため、パスだけではどのコミットが bind されているか
わかりません。取得元の行が、実際に bind されているコミットを示します。config はそのまま表示します。
${secrets.*} のプレースホルダは書かれたとおりに現れ、この画面で解決されることはなく(実行時にサーバの環境から
解決されます)、ファイル以上の開示はありません。ただし伏せ字にはしません。ローカルやアップロードした
config に平文で書かれた秘匿情報は、そのまま表示されます。秘匿情報はファイルに書かず ${secrets.*} の
参照にしておくことが、この画面に出さないための前提です。ホスト型のデプロイでは、このエンドポイントは
admin 限定です。
2 つの config の run を読み分ける¶
serve のプロセスは、一度に 1 つの config を bind します。別の config で再起動すると、両方の run が
1 つの履歴に混ざって並びます。これを分けるのがラベルです
(BE-0404)。
どの run も、実行した config を指す短い文字列を記録します。ローカルファイルならファイル名の語幹、
Git から取得した config ならリポジトリ名とリポジトリ内のパスです。run 一覧、Replay、
Stats ダッシュボードは、既定でそのラベルの run だけを表示します。
履歴全体に戻すには all labels を選びます。ラベルより前に記録された run しか持たないデプロイでは、
bind したラベルに一致する run が 1 件もないので、空のページではなく絞り込みなしの履歴が開きます。
別の区切り方をしたい運用者は、run ごとに指定できます。コマンドラインの bajutsu run --label <値> か、
POST /api/run の body の label フィールドです。Bajutsu にとってラベルは不透明な値で、解析も、
config との照合も、何を実行してよいかの判定への参照もしません。120 文字を超える値は、黙って切り詰め
るのではなく拒否します。切り詰められたラベルを履歴の中で見つけるのではなく、その場で気付けるように
するためです。
org を管理する¶
org は、ホスト型デプロイのテナントです。どの GitHub login、GitHub organization、GitHub Team がその org としてサインインできるか、そのうちどの Team が書き込めるかを決めます。書き込める Team もサインインを許されるので、そのためにもう1つエントリを書く必要はありません。データベースを繋いで動かすデプロイは、このメンバーシップを config ファイルではなくデータベースに持ちます。それを admin が編集する場所が Orgs タブです(BE-0375)。このタブが現れるのは、そうしたデプロイの admin に対してだけです。それ以外のデプロイでは、サーバが org の一覧を返さないので、タブは隠れたままになります。
各行には、org の slug、メンバーと GitHub organization と GitHub Team の数、editor Team が並びます。表示名が slug と異なる org では、その表示名も並びます。行の先頭にある slug と同じ文字列を二度出さないためです。Create は slug と表示名(任意)を受け取ります。作られた org のメンバーは1人もいません。メンバーシップを埋めるまで誰もその org としてサインインできないので、ページはその旨をその場に表示します。空のテナントが不具合に見えるのを防ぐためです。slug default は拒否します。どの org にも一致しないサインインが落ちる先であり、admin Team の迂回で入った admin も全員ここに入るので、そこに実在のテナントを置くと、admin が復旧に使う名前空間を奪ってしまうからです。この行は一覧には現れ、フォールバックである旨が添えられ、2つのボタンはどちらも無効になっています。迂回で入った admin 自身がここにいるからです。Membership を押すと、4つのフィールドをまとめて置き換えるフォームが開きます。フォームの初期値はサーバが現に持っている値です。変更は、各メンバーの次回のサインインから効きます。Delete は org を廃止します。廃止すると、その org としてセッションを持っている全員が同時にサインアウトされるので、廃止前に発行された cookie でその org として振る舞い続ける人は残りません。その org の run と監査記録は残り、slug も予約されたままです。3点とも後から気付きにくいので、確認ダイアログで明示します。
どの target を org が持つかは、引き続き config ファイルの orgs: ブロックが決めます。したがって、ここで作った org は、そこにエントリが書かれるまで1つも target を持ちません。
target を比較する¶
bind している config が target を 2 つ以上宣言していると、Comparison タブがそれらすべてを一度に 横断する読み取り専用の比較を開きます。「Android の target は通るのに iOS の target は落ちる」という、 単一の Stats ダッシュボードでは答えられない問いに答えるものです。 各 target が 1 行になり、実行回数、直近の合格率、フレーキ率(ウィンドウ内でフレーキと分類された シナリオの割合)、run あたり所要時間の中央値(p50)と 95 パーセンタイル(p95)、そして合格率の推移を 示すスパークラインが並びます。列見出しをクリックすると、合格率・フレーキ率・所要時間で並べ替えられます。 最初のクリックは最も注意すべき target(合格率が最も低い、あるいはフレーキ率や所要時間が最も高いもの)を 先頭に出し、もう一度クリックすると順序が反転します。まだ実行のない target は、誤解を招くゼロではなく 空欄の行になります。
行をクリックすると、その target の実行履歴が新しい順に開きます。ラベルで絞り込まない読み取り専用の
詳細です。この比較は 1 つの config の target どうしを並べるものであって、1 つのラベルの中だけを見る
ものではないからです。履歴にはキーボードからも到達できます。各行の target 名がボタンになっているので、
Tab でそこへ移り、Enter か Space を押します。この画面は何も書き換えません。target は binding では
ないので、有効化するものが存在しないからです。ほかのダッシュボードと同じく、run がすでに下した判定を
再表示するだけであり、何かを gate することはありません。
Settings¶
Settings には 3 つのタブがあります。AI と Secrets には AI を使うパスが必要とする選択があり、
Server(後述)は稼働中のサーバの設定を確認するための読み取り専用のタブです。AI タブと Secrets タブの
内容はディスクには書かれません。設定はそのセッションのあいだサーバのメモリ上に生き、serve を再起動すると
リセットされます。再起動をまたいで保持したい値は、serve を起動する前にシェルか .env で
ANTHROPIC_API_KEY / AWS_* を設定してください。
AI provider は、オーサリング(Record と Crawl)が使う backend を選びます。
- Anthropic API:従量課金の API です。下で設定する Claude API キーで認証します。
- Amazon Bedrock:AWS 経由の Claude です。標準の AWS 認証情報で認証し、AWS region と
Bedrock model id の欄が加わります(Bedrock の id はプロバイダ接頭辞を持ちます。例
global.anthropic.…。素の Anthropic id とは異なります)。 - Anthropic CLI(ant):公式の Anthropic CLI が持つ OAuth/SSO サインインを通じて、Pro/Max/Console
のシートで Claude を使います。API キーは不要で、どのパスでも画像入力(スクリーンショット)が使えます。
serveを起動した環境に CLI をインストールしておくと、Sign in with SSO ボタンがブラウザでの サインインを開始します(その環境でant auth loginを実行するのと同じです)。ボタンはserveが動く マシンでブラウザを開くので、ローカルのmake serveで使えます。ホスト型のデプロイではサーバがこの要求を 拒否し(403)、運用者が別途ホスト側でサインインします。 - Claude Code CLI(claude):
claudeCLI を介して、Claude Code の Pro/Max/Console サブスクリプションで Claude を使います。API キーは不要です。serveが動くマシンで一度claude setup-token(または対話的なclaudeログイン)でサインインしておきます。環境にANTHROPIC_API_KEYがあってもこの provider では 無視されるため、課金はサブスクリプション側に留まります。
ピッカーはプレースホルダから始まります。既定の provider はなく、明示的に選ぶまで Save は
拒否されます。各 provider 固有の欄(API キー、Bedrock の region と model id、CLI のサインイン)は、
その provider を選んだときだけ現れます。provider をまたいで効く上書きが三つあります。Model は
既定の代わりに特定のモデル id を使い(Bedrock は自前の接頭辞付き id 欄を保ちます)、Reasoning
effort はオーサリングのエージェントについて速度と深さを釣り合わせ(反映するのは Claude Code CLI
provider だけで、Anthropic API と ant の実装にはこの仕組みがなく、値は無視します)、Output language
(BE-0188)は
AI が生成する文章、すなわち record の from: 由来と crawl が逐次出力する推論テキストを、どの言語で書くかを固定します。
既定の auto は現状の挙動を保ちます(record はゴールに追従し、crawl は英語のままです)。決定論的な
run の判定には触れず、対象のデバイス locale とは別物です。
Claude API key(Anthropic API provider を選ぶと現れます)は write-once です。キーを入力して Save すると、以後はマスクした表示だけになり、 内容が再表示されることはありません。変更するには新しいキーを設定します。Clear で削除します。これは Anthropic API プロバイダで使われます(Bedrock は代わりに AWS 認証情報を使います)。 必要とするのは AI を使うパスだけです。Record と Crawl です。Replay は必要としません。 BE-0402 以降、そのアラートガードはネイティブ経路だけになり(BE-0315)、鍵なしで一般的なプロンプトを片付け、 鍵を参照もしないためです。
Scenario secrets(BE-0274)
は、バインド中の config が宣言するシークレット、つまりシナリオが ${secrets.X} として参照する
secrets: の環境変数名を一覧します(シークレット、
BE-0032)。宣言された名前ごと
に write-once のフィールドを並べ、API キーと同じくマスク表示だけで再表示はされません。これにより、
serve を起動する前に環境変数を export したり .env を手で編集したりしなくても、シナリオが必要とする
認証情報を Web UI から用意できます。ここで設定した値はその宣言済みの名前の環境変数に入り、spawn される
Replay / Record / Crawl が引き継ぐので、run のなかで ${secrets.X} が解決します。バインド中の
config がシークレットを宣言していないときも、このセクション自体は表示されたままで、機能を説明する
案内文が代わりに現れます。secrets: の内容が異なる config に切り替えると、一覧は更新されます。設定
できるのは config 自身が宣言している名前だけで、任意の環境変数を設定することはできません。ロールで
保護されたデプロイでは、設定は admin の操作です。
Server は、稼働中のサーバの設定を報告する読み取り専用のタブです
(BE-0318)。
デプロイモード(ローカルまたはホスト型)、バインド中の config とその取得元、このビルドが実行できる
backend、runs と baselines のディレクトリ、ゴミ箱の保持期間、並列実行数の上限、稼働中のバージョンを
示します。もっとも役立つ行は iOS test runner です。このビルドがバンドル済みの XCUITest Simulator
ランナー
(BE-0292)
を含むかどうか、含む場合はビルド対象の Xcode と Simulator SDK のバージョン、そしてバインド中の config が
明示的な xcuitest.testRunner でランナーを上書きしているかを示します。iOS の Simulator の run が
始まるかどうかは、この行だけで決まります。ホスト型のデプロイではホストのパス(config のパス、runs と
baselines のディレクトリ)を伏せますが、それ以外の行はどちらでも表示されます。このタブは入力を受け付けず、
起動コマンドと環境からすでに解決された値を報告するだけで、何も書き戻しません。
Record — ゴールからシナリオをオーサリングする¶
何をする画面か。 自然言語のゴールに向けて AI で探索し、その結果のシナリオを 1 手ずつ書き出します。
record コマンドをブラウザにしたものです。
操作手順。
- 目的を Goal (natural language) に書きます(例「カウンタを 2 回増やして 2 と表示されるか確認する」)。
- Target を選びます。iOS では Device も選びます(隣の更新ボタンでシミュレータを再取得できます)。 web では show browser (headed) にチェックを入れると、既定のヘッドレスではなく、目に見える Chromium のウィンドウがオーサリングを低速再生する様子を見られます。
- 必要なら Save as にシナリオのファイル名を入れます。空なら
generated.yamlが既定になり、同名が すでにあれば run の日時が付くので上書きされません。 - iOS のオプション:erase device first はシミュレータを初期化してアプリをオンボーディングから 始めます。disable alert-dismiss はこのオーサリング実行で vision のアラートガードを止めます。
- Generate scenario を押します(Stop で中止)。エージェントの 1 手ずつの進捗がログに流れます。
結果どうなるか。 オーサリングが終わると、Generated scenario パネルに YAML が出ます。必要なら その場で編集し、Save(保存するものが無いあいだは無効)を押します。シナリオはターゲットの scenarios ディレクトリに書き込まれるので、Replay タブの Scenario ピッカーに現れ、そのまま 実行できます。オーサリングループとアラートガードの仕組みは recording を参照してください。
その場で実行する。 Save の隣の ▶ Run ボタン(同じく YAML ができるまで無効)は、パネルの 現在の内容(オーサリングしたばかりのシナリオ、あるいは手で貼り付け・編集した YAML)をタブを 切り替えずに実行します。run 結果ペインが開いてライブのログと完了後のレポートを表示し、Stop で run を中断、閉じるボタンでペインを畳めます。合否は Replay タブと同じ決定的なランナーのものです。
Readiness(doctor)。 フォームには Check ボタン付きの Readiness パネルがあります。
doctor コマンドをブラウザにしたもので、Record と Replay の両タブで共通です。報告は二部構成です。
実行可能性のチェック(必要なツールが揃っているか、Simulator が起動しているか、web ターゲットの
ページに到達できるか)と、環境が実行可能なら現在の画面の慣習スコア(Ready / Partial /
Blocked のグレード、stable-id のカバレッジ、直すべき点の一覧(名前のないコントロール、
名前空間外の id、重複))です。ホスト環境を調べる読み取り専用かつ AI 不使用の診断で、run を
ゲートすることはありません。
Replay — シナリオを実行してレポートを読む¶
何をする画面か。 シナリオを決定的に実行し、そのレポートを埋め込みます。run コマンドをブラウザに
したものです。サブタブは Run と History の 2 つです。
Run。
- Scenario と Target を選びます。
- iOS では、実行する Simulators を選びます(停止中のものは先に起動されます。2 台以上選ぶと、 シナリオをそれらのあいだで並列に実行し、Workers がその台数に追従します)。erase device first と disable alert-dismiss は Record と同じです。web では show browser (headed) にチェックを入れると、 目に見える Chromium のウィンドウで実行を見られます。
- Run を押します(Stop で run を中断)。出力がログにライブ表示され、完了するとその run の
report.htmlが隣に埋め込まれます。run の前には、Record と同じ Readiness パネル(前述)が、 「環境は整っているか、アプリはアドレスできるか」にワンクリックで答えます(助言のみです)。
run の中断は、その run を捨てることではありません。 Stop はランナーに、自分の手順で run を
閉じるよう要求します。ランナーは完了しなかったシナリオを理由 cancelled で失敗させ、ふつうに失敗した
run と同じレポートを書きます。中断された試行は、ほかの失敗と同じように History に並びます。
「このシナリオは一度も実行していない」と「このシナリオは実行して中断した」を、履歴の上で区別できます。
最初のシナリオが始まる前(Simulator の起動中やアプリのビルド中)に中断した run は、今までどおりその場で
停止し、レポートを残しません。まだ合否に到達していないからです。Record タブと Crawl タブの Stop も
同じ理由で今までどおりです。どちらも run の合否を出しません。
ログパネルの下には Generate code バーがあり、選択中のシナリオをネイティブテストとして書き出します。 Author タブ(後述)と同じ codegen を、シナリオを走らせたその場所に置いたものです。
埋め込まれたレポートの中で、visual チェックの Approve ボタンは、その run が撮影した
スクリーンショットを visual ベースラインへ昇格させます(approve CLI コマンドと同じ昇格です)。以後の
run はそれと比較されます。これは run → 確認 → approve → 再 run というループの確認のステップです。
レポートの各セクションが何を示すかは reporting を参照してください。
History。 このサブタブは過去の run を新しい順に並べ、それぞれに pass/fail のドットとシナリオの 要約が付きます。クリックするとそのレポートを再表示します。更新ボタンで再取得します。
run を削除する(BE-0239)。 各行にはゴミ箱ボタンがあり、その run(レポート、スクリーンショット、動画、ネットワークキャプチャ)を Trashへ移します。すぐに消し去るのではなく、保持期間の あいだは復元できる状態で残ります。まとめて片付けたいときは、各行のチェックボックス(または select all)で 選び、一覧の上のバーの Delete selected を使います。どちらも editor 権限の操作です。ソフトデリートした run は履歴からすぐに消え、復元すれば元の履歴に戻ります。
失敗した run を triage する。 run が失敗すると、レポートバーに Triage ボタンが現れます(実行直後の
レポートでも、History から失敗した run を開き直したときでも表示されます)。triage コマンドをブラウザに
したもので、ターミナルに移らずに「なぜ失敗したのか」をその場で調べられます。ボタンを押して Diagnose を
クリックすると、triage はその run が残した失敗コンテキストを読み、根本原因の要約、問題のステップ、対処の
候補を示します。既定は決定的なルールベースのエージェントです。Claude にチェックを入れると(AI プロバイダを
設定しているときだけ有効になります。Settings を参照してください)、Claude の調査エージェントで
診断します。triage がセレクタ id の改名、一致の絞り込み、タイムアウトの引き上げといった機械的な修正を
提案できるときは、その修正を、いま選んでいるシナリオのソースに対する diff として表示します。Apply fix
は、その差分を Author タブと同じ検証済みの保存経路を通して書き戻します。Apply & re-run は書き戻したうえで
すぐにシナリオを再実行し、修正が効いたかを確認します。修正が書き込まれるのは、この明示的なクリックのときだけ
です。自動では何も編集しませんし、run の合否は決定的な run が出したものを読み取るだけで、AI が計算し直すことは
ありません。triage は Run サブタブでいま選んでいるシナリオに対してプレビューと適用を行うので、History から
run を triage するときは、対応するシナリオとターゲットを先に選んでおいてください。
Crawl — アプリを探索して画面マップをその場で描く¶
何をする画面か。 アプリを幅優先で探索し、到達できる画面と画面間の遷移を、発見に合わせて描きます。
crawl コマンドをブラウザにしたものです。これは発見のためのツールで、合否ゲートには決してなりません。
探索エンジン(画面の同一性、遷移、クラッシュ判定)は決定的で、Settings で選んだ AI プロバイダは
「何を試すか」を提案するだけです。
操作手順。
- Target を選び、Workers(並列のブラウザプロセス数。iOS では 1 つの画面マップを共有する シミュレータ数)を設定します。iOS では、クロールする Simulators も選びます。
- 予算を設定します。Max screens(既定 50)と Max steps(既定 200)です。クロールは先に達した方で 停止します。
- iOS には erase device first と disable alert-dismiss、web には show browser (headed) が あります。
- Start crawl を押します(Stop で中止)。進捗はステータス行と Console に出ます。
得られるもの(フォームの隣の 3 つのビュー)。
- Screen map:発見した画面と遷移のグラフで、クロールの進行に合わせてライブで描かれます。− / リセット / + で拡大縮小します。同じ UI で一時的な状態だけが違う画面(未入力と入力済みのフォームなど)は 1 つのノードにまとまり、その場で展開できます。
- Exploration plan:画面ごとの未試行操作を並べた計画ツリーで、進捗バーが付きます。show pruned は、 クロールが重複するグローバルコントロール(一度だけ探索したタブやナビゲーションバー)として刈り込んだ 操作の表示を切り替えます。それらは取り消し線付きで表示され、クリックすると探索を再開できます。
- Console:クロールの進捗ログです。
マップの画面をクリックするとスクリーンショットのライトボックスが開きます。拡大された画面に ‹ / › が付き、その画面への遷移や、その画面からの遷移へ移動できます。ホットスポットは、各遷移がどこで 起きたかを示します。
履歴。crawl は manifest.json を書かないため、Replay タブの History には現れません。crawl の run
は、Crawl タブ自身の History サブタブに一覧されます。どの crawl も書き出す screenmap.json を手が
かりにしていて、各エントリには run の ID と、画面・遷移・クラッシュの件数が新しい順に並びます。エント
リを選ぶと、その crawl の画面マップが読み取り専用で開きます。保存済みのマップから描き直すだけで、
crawl はやり直しません。実行中の run と取り違えないように past crawl バッジが付き、表示している間は
入力フォームが無効になります。マップの隣には、その run の crashes/*.yaml(再現できるクラッシュ)と
flows/*.yaml(到達できる画面)のシナリオファイルへのリンクが並びます。いずれも生の YAML が開き、
bajutsu run でそのまま実行できます。Form サブタブに戻ると、実行用の crawl フォームに戻ります。
crawl を削除する(BE-0239)。 Replay の History と同じく、各 crawl の行にゴミ箱ボタンがあり、select all と Delete selected の バーでまとめて片付けられます。削除した crawl は共通の Trashへ 移り、保持期間内なら復元できます。
過去のクロールの続きから探索する(BE-0181)。 開いている過去の run が予算で止まり、まだ探索していない画面が残っている場合は、マップのヘッダに ▸ continue exploring ボタンが現れます。これを押すと読み取り専用の履歴表示を抜け、その run を続きから 探索します。残りのフロンティア全体(未試行の操作が残るすべての画面)を再探索し、同じマップに追記します。 このとき現在の Max screens / Max steps をそのまま使うので、同じ操作で予算を上げられます。また Workers や選んだシミュレータで continuation を並列に実行します。過去の run を開いた状態で、取り消し線の 付いた pruned 操作をタップすると、その 1 つのブランチだけを続きから探索します。どちらも明示的な操作 です。履歴表示は探索を指示するまで読み取り専用のままなので、過去のマップを誤って動かすことはありません。
画面マップ、画面を同定する fingerprint、web と iOS の違いは CLI リファレンス で扱います。
Trash — 削除した run を復元するか完全に削除する¶
何をする画面か(BE-0239)。 Replay や Crawl の History で削除した run が、ここにゴミ箱として並びます。通常の run と crawl の run は 1 つのゴミ箱を共有し、それぞれに削除した時刻が付きます。ソフトデリートは消し去る操作ではありません。run は 履歴の一覧から外れますが実体は残るので、Restore を押せば元の履歴へそのまま戻ります。
保持期間。 ゴミ箱に入った run は、保持期間(BAJUTSU_RUN_RETENTION_DAYS。既定は 30 日で、0
にすると手で削除するまで残ります)を過ぎると完全に削除されます。この掃除は遅延実行で、次に履歴かゴミ箱を
読んだときに行われ、バックグラウンドのタイマーは使いません。サーバがアイドルのあいだは何も動きません。
ヘッダには、いま効いている保持期間が表示されます。
完全に削除する。 ゴミ箱の各 run には、保持期間を待たずにその実体をすぐ消す Delete forever の操作も
あります。取り消せない操作なので、ホスト型のデプロイでは admin 権限に限ります(ローカルの単一ユーザーの
serve には権限の区別が無いため、そちらでは常に使えます)。確認ダイアログも、通常の削除とは別の、より強い
警告のものになります。削除・復元・完全削除はいずれも監査ログに記録され、oplog イベント
(run.soft_deleted / run.restored / run.purged)としても出ます。運用担当者は、誰がどの run を
いつ消したかを追えます。
Author — 1 つのシナリオを capture・edit・enrich する¶
何をする画面か。 1 つの開いているシナリオを、Capture / Edit / Enrich のボタンで選ぶ 3 つのモードで扱います。モードを切り替えても、シナリオが読み直されたり未保存の YAML 編集が失われたりは しません。
Capture:実際のスクリーンショットをクリックしてシナリオを組み立てます。
- Target を選び、Start capture を押してライブセッションを始めます。
- Action mode を tap か type にし(type のときは Text to type を埋めます)、 スクリーンショットをクリックして各操作を記録します。
- Finish & save を押して、記録したフローを書き出します。
Edit:過去の run か、ライブセッションのスクリーンショットに対してステップを直します。
- Scenario を選んで Load を押します。Run ピッカーにはそのシナリオ自身の過去の run だけが並ぶので、選んだ run のステップが読み込んだシナリオと食い違わずに対応します。Run を選ぶと、その run が撮影したスクリーンショットをたどれます。
- 過去の run がないときは、Start live session を押すとターゲットを起動して現在の画面に対して要素を選べます。Edit に run は要りません。Stop session で保存せずに終了します。
- ← Prev / Next → でステップを移動します。ラベルにどのステップを読み込んでいるかが出ます。
- スクリーンショットをクリックして読み込んだステップの対象を付け替え、Apply でその変更を YAML に反映します。run から読み込んだスクリーンショットも、クリックの解決に使う要素ツリーも、そのステップが動作したあとの瞬間を表します(レポート)。そのため画面を移すステップでは、そのステップが対象とする画面ではなく、移ったあとの画面が出ます。こうしたステップを付け替えるときは、ライブセッション(手順 2)を使ってください。
Enrich:提案されたアサーションを加えます。
- シナリオを読み込み、Enrich を押します。
- Proposed assertions パネルに提案が並びます。Accept で YAML に取り込み、Dismiss で 破棄します。
YAML エディタ(3 モード共通)は入力しながら検証します。デバウンスしたチェックが bajutsu lint と
同じルールを実行し、行に紐づく診断を、該当行のガターのマーカーと、クリックできる問題リストとして
表示します。問題をクリックするとその行へ移動します。シナリオの JSON Schema は、軽量なキー補完
(Ctrl/⌘+Space)と hover の説明表示にも使われます。これは決定的で、AI を使いません。Save で
シナリオを書き出します。これらのチェックが従う文法は scenarios、セレクタの採点方法は
selectors を参照してください。
決定性の監査バッジは、lint と同じライブの YAML を安定性の観点で採点します。グレードのバッジ
(Stable / Moderate / Fragile と、id ベースのセレクタの割合)がエディタのヘッダに表示され、
エディタの下の findings 一覧が決定性リスクを一つずつ挙げます。安定性ラダーより下のセレクタ、具体的な条件を
持たない wait、生座標のジェスチャです。これは audit コマンドの静的スコアをブラウザに出した
もので、読み取り専用でデバイスも AI も使わず、あくまで参考情報でありゲートにはなりません。Replay タブ
でも、選択中のシナリオに対して同じバッジを表示します。シナリオを書く場所でも実行する場所でも、安定性の
シグナルが見えるようにするためです。
Generate code:読み込んだシナリオを、ブラウザを離れずにネイティブテストとして書き出します。
シナリオを読み込んで Generate code を押すと、結果が読み取り専用のビューアに開き、Copy で
コピー、Download でダウンロードできます(ファイル名はシナリオと出力先から導きます。例:
LoginUITests.swift / login.spec.ts)。出力先はターゲットの backend に従い、iOS なら XCUITest、
web なら Playwright になるので、そのターゲットが対応する形式だけを提示します。これは
codegen コマンドを UI に出したもので、シナリオを出力先フレームワークの流儀へ構造的に
対応づけるだけです。デバイスも AI も動かさず、合否も計算しません。未対応の限界は codegen 自身のものです。
Stats — run 履歴のダッシュボード¶
何をする画面か。 サーバの run 履歴を横断した集計 run 統計ダッシュボードを描きます。stats コマンドを
ブラウザにしたものです。これは読み取り専用かつ助言的で、判定ではありません。合格率の推移、遅い
シナリオと flaky なシナリオ、失敗ホットスポット、run のボリュームを、各 run の保存済み manifest.json から
集計します。シナリオの行には、系列を束ねている内容フィンガープリントを併記します。run と run の
あいだにシナリオを編集すると系列は分かれますが、フィンガープリントを見れば、同じ行の重複ではなく
別々の系列だと読み取れます。ダッシュボードが集計する run の範囲は、Replay タブの履歴一覧が並べる
最新 run の範囲に必ず含まれます。データベースを配線しているときは両者が同じ範囲になり、配線して
いないときは履歴一覧に上限がないぶん、ダッシュボードの範囲はその一部になります。いずれの場合も、
ドリルダウンで開いた履歴が、開く元になった行と食い違うことはありません。
操作手順。 タブを開くとダッシュボードが読み込まれます。更新ボタンで、現在の run 履歴に対して 再集計します。デバイスも AI も run も関わりません。
Flaky — ランク付きのフレーキシナリオ一覧¶
何をする画面か。 サーバの run 履歴を、各シナリオの判定がフィンガープリント一定のままどれだけ反転するかで
並べ替えます。flakiness コマンドをブラウザにしたものです。これは読み取り専用かつ助言的で、判定ではありません。
シナリオを判定の反転率で flaky を先頭に並べ、各行は pass/fail の数と分類(flaky / deterministic / unproven。
決定性監査から再利用します)を示し、代表的な合格 run と失敗 run の証跡へリンクします。データベースを配線している
ときは各 run の行に刻まれた provenance から直接グルーピングし(org スコープ)、そうでなければ各 run の保存済み
manifest.json から同じレコードを組み立てます。
操作手順。 タブを開くとランキングが読み込まれます。更新ボタンで、現在の run 履歴に対して再集計します。 フィンガープリントを持たない run や、判定が記録されていない run はグルーピングできず、スキップとして報告します。 デバイスも AI も run も関わりません。
フラッキーなシナリオを診断する。 AI による Run 横断の修正提案は、CLI の機能 bajutsu triage --flaky です
(このパネルが名指ししたシナリオの成功 run と失敗 run をまとめて読み、差分を説明します。CLI リファレンスを参照)。これは設計上 CLI 専用です。この
パネルは決定的なランキング(AI 不使用)である一方、Run 横断の提案は AI プロバイダを必要とし、人がレビューして
適用するための差分にとどまるためです。
Usage — AI トークン利用量とコストのダッシュボード¶
何をする画面か。 AI パス(record、crawl、triage、アラートロケータ)が記録した属性付きの利用 ledger を もとに、AI の利用量とコストのダッシュボードを描きます。Stats と同じく読み取り専用で助言的であり、判定にも ゲートにもなりません。期間内の合計(トークン数とドル)、provider・model・command・scenario 別の内訳、 provider と model の比較(1 コールあたり・1 シナリオあたりのコスト)、日次のコスト推移を示します。どの数字も ledger 上の決定的な合計で、モデルは使いません。サブスクリプションの provider や未知の model はトークン単価を 持たないため、そのコールはドル額を捏造せず未価格(「—」)として示します。
操作手順。 タブを開くとダッシュボードが読み込まれます。更新ボタンで、現在の ledger に対して再集計します。
どのファイルを読むかは、ledger を書く AI パスと同じ解決方法に従います。参照するのは defaults に
ターゲットの設定をマージした ai ブロックなので、targets.<name>.ai.usageLedger がチーム共通の
defaults.ai.usageLedger を上書きします。ターゲット
ごとに別の ledger を指定した設定では、指定されたすべての ledger を読んで合算します。ダッシュボードが対象と
するのは、1つのターゲットではなく serve プロセス全体だからです。
まだ利用が記録されていないとき(AI パスを一度も実行していない、または永続化を無効にしている場合)は、記録を
有効にする方法を説明する空の状態を表示します(ledger の既定は runs/usage.jsonl で、ai.usageLedger で
移動でき、空文字で無効化できます)。デバイスも AI も run も関わりません。
Coverage — E2E カバレッジマップ¶
何をする画面か。 ターゲットの E2E カバレッジマップを描きます。coverage コマンドをブラウザにした
ものです。シナリオスイートが参照する安定 id を、アプリが宣言した idNamespaces と突き合わせ、名前空間
ごとのカバレッジ、不足の一覧(どのシナリオも触れていない宣言済み名前空間)、名前空間から外れた id を
示します。run が実行時に束縛するセレクタ、つまり totp や email ステップの出力を受け取る
${vars.*} プレースホルダは、どの要素も指していません。マップはプレースホルダの文字列を id として
数えず、対象から外します。
過去の run を選ぶと、run の証跡に基づく次元が加わります。観測されたエンドポイントとアサートされた
エンドポイントの比(選んだ run の network.json の和集合を、スイートのネットワークアサーションと
突き合わせたもの)と、観測された id と宣言済み名前空間の比(各 run の elements.json から)です。
選んだ run に加えてクロールも選ぶと、screens-visited の次元が加わります。そのクロールが
screenmap.json に記録した発見済み画面のうち、選んだ run がどれだけ到達したかを示す次元です。
測る対象がない次元は、バーを満たす代わりにその旨を書きます。名前空間を1つも宣言していないターゲットは
分母が空であり、それをカバレッジ 100% として描けば、読み手に事実と正反対のことを伝えてしまうからです。
Stats と同じく、この画面全体が読み取り専用で助言的であり、判定にもゲートにもなりません。どの数字も
決定的な数え上げで、モデルは使いません。
操作手順。 ターゲットを選び、Compute を押すとマップが描かれます。run のピッカーには、その ターゲット自身のシナリオを実行した run だけが並びます。別のターゲットのシナリオを実行した run は、 このマップが位置づけられない証跡を運んでくるからです。run を選ぶと run の証跡に基づく次元が加わり、 さらにクロールを選ぶと screens-visited の次元が加わります。クロールの一覧は同じようには絞り込まれません。 クロールは絞り込みの鍵となるターゲットを記録していないからです。同じアプリのクロールを選んでください。 別のアプリのクロールを選ぶと、すべての画面が未訪問として測られます。デバイスも AI も run も関わりません。
直接開く。 GET /coverage?target=<名前> は、同じマップを単体のページとして描きます。/stats、
/flakiness、/usage と同じように、カバレッジマップにリンクを張ったりブックマークしたりできます。
run の証跡に基づく次元には &runs=<id>,<id> を、screens-visited の次元には &crawl=<id> を足します。
セキュリティとホスティング¶
既定の make serve は 127.0.0.1 に無認証で bind します。loopback インターフェースでのみ安全です。
自分のマシンの外に公開するにはトークン(--token)が要ります。トークンは認証と CSRF 対策を有効にし、
非 loopback の --host への bind にはトークンが必須です。単一 Mac でのチーム向けホスティング
(--emit-launchagent)や本格的なコントロールプレーンの backend(--backend server)、そして
--max-concurrent-runs と --evidence-store は、CLI リファレンス と
self-hosting で扱います。
サインイン。 認証付きのサーバでは、最初に未認証で返ってきた要求がサインインの入り口になります。 GitHub OAuth が設定されていればブラウザがそこへ送られ、そうでなければトークンの入力プロンプトが 出ます。共有トークンを入力すると、以後はセッションクッキーがサインイン状態を保ちます。ローカルの 無認証サーバでは、どちらも現れません。
各タブのスクリーンショットは今後追加する予定です。現時点では本文だけの案内です。