はじめての再現を書く
// GUIDE · 再現を書く
ブラウザだけで動く Layer 1 レシピを 1 つ書く。
既存レシピをコピーしてスラッグと再現スクリプトを差し替えるだけで、Vivarium 互換の再現ページが手元で動く。完成したらアップストリームへ PR を送るか、自分のフォークに置き続けるかを選べる。
// 0 · このガイドが対象にするもの
Layer 1(ブラウザ内 WASM)の最小レシピ。
Layer 1 は Pyodide、
Ruby.wasm、php-wasm、
Rust の wasm32-wasip1 ターゲットなどで上流コードを
ブラウザに持ち込み、ページが開いた瞬間に再現スクリプトを走らせて
verdict を返す層です。インストール不要・サーバー不要なので、
Vivarium に最初に追加するレシピとして最もコストが低いです。
Layer 2(Docker)と Layer 3(record-replay)はそれぞれ アーキテクチャ に役割が書かれていますが、書き始めるならまず Layer 1 一択です。
このガイドはレシピを書くところまでを対象にします。 その先「どこに公開するか」は 2 分岐で、 自分のフォークで動かす または上流リポジトリへの PR、のどちらかです。
// 1 · 再現したいバグを決める
スラッグは <project>-<issue> 形式。
上流 Issue がある場合は <project>-<issue>
(例: pandas-56679)が標準。
ない場合は説明的なケバブケース(例: bash-local-shadows-exit)。
これがディレクトリ名でもあり、Manifest v1 の slug でもあります。
バグを選ぶときは、Layer 1 で完結するか確認するのがコツです:
- 外部 I/O(ネットワーク、ファイル、サブプロセス)を踏まない。
- verdict が 1 つの真偽値に落ちる(例: 「2 つの値が等しいか」)。
- 必要なライブラリが対象ランタイムの WASM ビルドに乗っている(Pyodide / Ruby.wasm / php-wasm の同梱パッケージ一覧)。
// 2 · クローンして雛形をコピーする
一番近い既存レシピを丸ごとコピーするのが最短。
アップストリームに PR したいなら aletheia-works/vivarium を直接クローン、自分のフォークに置きたいなら フォーク手順 でフォークしてからクローンします。
mise install でリポジトリ直下から bun など必要なツールが入ります。Layer 1 用には cd src/layer1_wasm 配下で bun install も走らせてください。
言語が同じレシピを丸ごとコピーするのが楽です。Python なら src/layer1_wasm/pandas-56679/、Ruby なら ruby-21709/、PHP なら php-12167/、Rust なら regex-779/。cp -r src/layer1_wasm/pandas-56679 src/layer1_wasm/<あなたの slug> でディレクトリごと複製。
// 3 · index.html を書き換える
差し替えるのは title、見出し、lede の 3 か所。
コピーした index.html の構造はそのまま使い、以下を上流バグに合わせて差し替えます:
<title>— タブに出るタイトル(例:Vivarium · Reproducing <project>#<issue>)。<h1>— 見出し。上流 Issue へのリンクを含めます。<p class="lede">— 1〜2 文でバグを説明する lede。
触ってはいけないもの: <meta name="vivarium-contract" content="v1">、
#verdict 要素、../_shared/style.css へのリンク。
これらが Contract v1 を構成しているので、外すと verdict が機械的に読めなくなります。
Contract v1 の正典は Contract v1 にあります。
data-verdictの取りうる値、VIVARIUM_RESULTenvelope のスキーマは spec ページが正です。
// 4 · repro.ts を書き換える
再現ロジックだけ差し替える。helper はそのまま。
コピー元の repro.ts は ../_shared/loader.js と
../_shared/verdict.js を import している部分が共通骨格です。
ここはそのまま残して、再現コード本体だけ差し替えます。
Python レシピなら以下のような形:
const REPRO_CODE = `
import pandas as pd
# ↑ 上流バグを表す最小コード
result = {
"left": ..., # 比較する値 1
"right": ..., # 比較する値 2
"mismatch": <left> != <right>,
}
result
`.trim();
verdict 設定は helper が面倒を見ます: 比較が true(バグが再現した)なら
setVerdict("reproduced", "...")、そうでなければ
setVerdict("unreproduced", "...")。
setResult({ contract: "v1", bug, runtime, result, timing })
で VIVARIUM_RESULT envelope も書き出されます。
// 5 · ローカルで動かす
bun run build → 静的サーバ → ブラウザで開く。
# src/layer1_wasm/ から
bun install
bun run build # repro.ts → repro.js を生成
# レシピディレクトリを直接サーブ
python -m http.server -d src/layer1_wasm/<あなたの slug> 8765
# ブラウザで http://localhost:8765/ を開く
ページが開き、上流ライブラリが CDN からロードされ、
verdict バッジが pending →
reproduced / unreproduced のどちらかに落ちます。
DevTools コンソールで VIVARIUM_VERDICT と
VIVARIUM_RESULT も同じ値が入っていれば、
Contract v1 上は OK です。
Pyodide / Ruby.wasm / php-wasm はいずれも
SharedArrayBufferを使わない構成にしてあるので、COOP/COEP ヘッダは不要です。 普通の静的サーバ(python -m http.serverやbunx serve)で動きます。
// 6 · ネイティブ再検証(任意)
ブラウザ外でも同じバグが出ることを 1 行で確かめる。
Pyodide / Ruby.wasm 経由で観測できたバグが、本物の CPython / MRI Ruby でも同じく再現することを示すと、レシピの説得力が上がります。 Python なら uv + PEP 723 inline metadata で 1 ファイル完結に書けます:
# /// script
# requires-python = ">=3.13"
# dependencies = ["pandas==2.3.3"]
# ///
import pandas as pd
# … 同じ再現ロジック …
mise exec uv -- uv run repro.py で ephemeral venv
が組まれて走ります。Ruby、PHP、Rust も同様で、既存レシピの
repro.rb / repro.php / Cargo.toml
が雛形になります。
// 7 · recipes.json を再生成
ギャラリーに自分のレシピを並べる。
ギャラリー(/repro/)と MCP サーバが読む
recipes.json は、ビルド時に
src/layer*/ をスキャンして自動生成されます。
手元での確認用には:
mise run recipes:index
# あるいは
cd docs && bun run generate-index
生成された docs/public/api/recipes.json に
自分のスラッグが入っていれば成功です。
docs サイトをローカルで動かすと、ギャラリーにカードが現れます:
cd docs && bun run dev
# http://localhost:3000/vivarium/ja/repro/// 8 · どこに公開するか
上流 PR か、自分のフォークか。
aletheia-works/vivarium 上で feat(layer1): add <slug> reproduction のような Conventional Commits で PR を立てます。レビュー基準は既存レシピを見れば分かりますが、最低限 Contract v1 に従っていれば CI が緑になります。
レシピを自分の vivarium フォークの main に push し、フォーク手順 の deploy 設定を有効化すると、自分の <you>.github.io/vivarium/ に並びます。共有は URL を渡すだけ。
自分のプロジェクトリポジトリ側で「このレシピを CI で監視する」だけしたい場合は、レシピを書く必要はありません。自分のリポジトリに統合する に Manifest v1 と consumer-workflow.yml を使う最短手順があります。
手順のどこかで詰まったら、それは write-your-first-reproduction のバグです。詰まったステップ番号を Issue に残してください。