要点: 「何か変わったか?」に1つのコマンドで答える
transform をリファクタリングする、Toolを更新する、Packのバージョンを差し替える。そのあとで、観測可能な振る舞いが変わったかどうかをエンジンに尋ねます。既知の良好なRunからJournalを記録しておけば、あとで --verify 付きでリプレイしたときに、何も変わっていなければ静かに通過し、出力が一致しなくなった最初の手順で明確に失敗します。
search-price@1.2.0 が製品価格を読み取り、transform 手順がそれを整形し、条件付きの http.post がシークレットのwebhookに通知します。
Step 1 — Journalを記録する
任意のbrowserflow run に --record-journal <path> を追加します。Runは通常どおり実行されます。browser Toolは実際のページを操作し、http.post は実際に発火します。そして、すべての読み取りと効果が、指定したJournalファイルに取り込まれます。
run_started、step_started、step_succeeded(output_digest を持つ)、effect_recorded(result_digest を持つ)、run_finished が、実行モデルで定義された形で記録されます。fixtureとしてコミットする前に、いくつかの性質を理解しておく価値があります。
- シークレットは含まれません。 シークレット値は解決するToolの内部でだけ実体化し、recorderはリクエスト形状をJournalに書き込む前に、シークレット由来のバイト列を安定したプレースホルダー(
{secret:<slot>})にredactします。webhookの認証ヘッダーはfixtureに入りません。シークレットを漏らさず効果を記録するを参照してください。 - 大きな本文はインラインではなくdigestで保存されるため、Journalは小さいままです。大きすぎるpayloadはartifact参照になります。
- 生成されたartifactの既定の保存先は
out/です。 fixtureとして保持したいJournalをコミットするのは、たとえば./fix/配下に置くような、意図的な選択です。偶然ツリーに入るものではありません。
Step 2 — hermeticにリプレイする
browserflow replay の既定は hermetic モードです。注入される net、clock、random、fs-read、browser capabilityは、完全にJournalによってbackされます。外部呼び出しは一切行われず、シークレットも不要です。記録済みの効果は、単に記録済みの結果を返します。
--verify を追加すると、エンジンはすべての手順出力が記録済みのdigestとまだ一致していることをassertします。Toolのアップグレード、transform の編集、依存関係の変更によって振る舞いがずれると、リプレイは最初に分岐した手順で明確に失敗します。pureなtransformは無料で再実行されてチェックされ、記録済みの読み取りはJournalから提供されてチェックされ、digestが一致しない瞬間にrunは停止します。どちらのhermetic形式も常に副作用がなく、promptも出さないため、どのpipelineにも安全に組み込めます。
Hermeticと --rerun
2つのリプレイモードは決して混同されません。HermeticリプレイはJournalから再現し、何にも触れません。--rerun はJournalから読み取りをリプレイしますが、効果はライブで再実行し、実際のシステムに対してwriteを再発火します。
- Hermetic(既定 / --verify)
- --rerun (live)
- 読み取り(
net、clock、random、fs-read、browser): Journalから提供されます。 - 書き込み / 効果(
http.post): 発火しません。記録済みの結果が返されます。 - シークレット: 不要です。Journalにも存在しません。
- 外部呼び出し: どの種類もありません。
- ネットワーク / 接続性: 不要です。完全にair-gappedで実行されます。
- 副作用: ありません。promptも出ません。
- 用途: runが何をしたかを監査する、リファクタリングを回帰テストする、隔離環境で再現する。
| 観点 | Hermetic(replay / --verify) | --rerun |
|---|---|---|
| 読み取り(net/clock/random/fs-read/browser) | Journalから | Journalから |
効果 / 書き込み(例: http.post) | Journalから返され、発火しない | ライブで再実行 |
| 外部呼び出し | なし | あり(効果に対して) |
| 必要なシークレット | なし | あり。実行時に再解決され、Journalからは読まれない |
| 接続性 | なし(air-gapped可能) | 必須 |
| prompt / 確認 | なし | run と同じように効果を確認 |
--verify の出力assertion | あり | n/a |
--rerun でもシークレットが必要な理由: 記録済みのJournalは、すべてのシークレット由来のバイト列を {secret:<slot>} プレースホルダーにredactするため、値は本当に存在しません。writeを再発火するには、エンジンが設定済みのシークレットプロバイダーから実行時にシークレットを新しく再解決します。これは通常の run とまったく同じであり、resumeともまったく同じです。Step 3 — JournalをCI回帰fixtureとして固定する
Hermeticリプレイに必要なのはJournalだけなので、理想的なCI gateになります。flowと一緒にJournalをコミットし、すべての変更で--verify によって静かな振る舞いのドリフトを防ぎます。
既知の良好なJournalを記録してコミットする
flowを一度現実に対して実行し、Journalを取り込み、意図的なfixtureとしてリポジトリにチェックインします(Journalの既定の出力先は、それ以外ではgitignoreされた
out/ です)。すべてのpushで検証する
pipelineにhermeticな
--verify を追加します。シークレットも、ネットワークも、browserも不要なので、どのmachineでも高速かつ同一に実行されます。--verify は期待ではなく証明です。同じ入力と同じ記録済み効果が与えられれば、flowは今も同じ出力を生成します。周辺のpipeline、つまりキャッシュ、pinされたTool、compile --check については、CIで実行するを参照してください。
ファイルだけでなく、保存済みrunをidでリプレイする
ファイルだけでなく、保存済みrunをidでリプレイする
browserflow replay は、<journal> ファイルパスまたはローカルストアの <run-id> のどちらも受け付けます。id形式は、このmachineですでに実行したrunをリプレイします。ファイル形式は、machine間で移動してコミットする持ち運び可能なfixtureです。どちらも --verify と --rerun を同じように扱います。--verifyは正確には何を比較するのか?
--verifyは正確には何を比較するのか?
各
step_succeeded イベントは output_digest を持ち、各 effect_recorded イベントは result_digest を持ちます。リプレイ時、エンジンは各手順の出力を再計算し、そのdigestを記録済みのdigestと比較します。pureな手順(capabilityを宣言しない transform)は最初から再実行されてチェックされます。capabilityにbackされた読み取りはJournalから提供され、そのdownstream出力がチェックされます。最初の不一致でrunは停止します。今日の価格が違うとhermeticテストは失敗するのか?
今日の価格が違うとhermeticテストは失敗するのか?
いいえ。Hermeticリプレイは
browser の読み取りをJournalから提供するため、flowが見るのは記録済みの価格です。Hermeticな --verify は、あなたのコード変更を世界の変化から切り離します。Webサイトではなく、flowをテストします。ライブサイトに対して確認したい場合は、効果を再発火しながら読み取りは引き続きJournalから提供する --rerun を使うか、単に新しい browserflow run を実行してください。リプレイはresumeと同じか?
リプレイはresumeと同じか?
同じ仕組みを共有しますが、意図が異なります。Resume は、中断されたrunをそのfrontierから継続し、すでに記録済みのものは何も再発火しません。Replayはresumeのofflineな親戚です。監査、回帰、air-gappedな再現のために、完了済みrunを再現します。どちらでも、シークレットだけはJournalから決して読まれません。ライブで再解決されます。
関連
CIで実行する
compile --check とpinされたToolとともに、--verify をpipelineに組み込みます。実行と再現性
Journal、決定論性、resume、2つのリプレイモードが実際にどのように機能するか。
CLIリファレンス
browserflow run、browserflow replay、browserflow inspect の完全なflagと例。シークレット
--rerun でシークレットが再解決され、Journalには決して記録されない理由。