PRデモ
レビュアーは、コード差分を開かなくても1分以内に変更内容を理解できるべきです。変更点、新しい動作、動作確認の証拠、そしてどこを見ればよいか。リポジトリの設定情報(キャプション言語、変更フローの録画方法、投稿先)は .claude/profiles/delivery.md に記載されています(Demo、Notify セクション)。
簡潔で率直なものが、完全なものに勝ります。 以下の順序で、合計30秒・5シーンに収めます。変更にないものは無理に追加せず省略してください。
- 変更内容 — タイトルと最大3つの箇条書き。
- 新しい動作 — フロー図。変更箇所をマーク。
- Before/After — 視覚的な変更がある場合のみ。バックエンド変更ではスキップ。
- 修正の動作確認 — 録画。重要な部分だけにトリミングし、12秒未満。
- 証拠 — レビューキーのチェック結果 と テスト結果を1つの
keyシーンにまとめる。両者は同じ疑問に答えるため、それぞれ別シーンにはしない。
1. 素材の収集
out/demo/<PRまたはIssue番号>/ ディレクトリに保存します(git管理対象外)。
- レビューキーのエビデンス:
out/review-key/<番号>/result.jsonおよびkey-reviewerの判定結果(review-key)。 - UI変更のスクリーンショット: 同じビューを変更前(ベースブランチ)と変更後で、同じサイズ・同じデータで比較。変更部分のみにトリミング。1280pxの全ページだと変更が小さすぎて見えません。
- 変更フローの録画: プロファイルの Demo コマンド、またはPlaywrightで
browser.newContext({ recordVideo: { dir, size: { width: 1280, height: 800 } }, viewport: { width: 1280, height: 800 } })を使用してE2Eテストの該当ステップを録画(コンテキストクローズ時にファイル生成)。20秒未満に保ち、重要な画面から始め、ログイン画面は映さない。 - 変更のフロー図: mermaid
flowchart LR(またはTD)。5~9ノードでユーザーまたはリクエストの経路を示す。変更箇所に:::changed、新規追加に:::added、削除に:::removedを付ける。ファイルではなく動作を説明する。 - 実行したテスト: 各テストに数値を1つ(
476 tests、12 flowsなど)。
2. demo.json の作成
素材と同じディレクトリに配置します(パスは相対パス)。テキストはプロファイルのキャプション言語で記述。短文に — 各シーンは表示秒数内で読まれます。バッククォートと **太字** が使用可能です。
{
"lang": "en",
"brand": "**shop** · PR #352",
"ref": "Closes #331",
"kicker": "Bugfix",
"title": "The checkout fits at 1280 px",
"subtitle": "The pay button covered the basket, and the coupon field was 49 px wide.",
"chips": [{ "text": "Review key: PASS", "ok": true }, "3 files"],
"scenes": [
{ "type": "title", "seconds": 3 },
{ "type": "bullets", "items": ["…", "…", "…"], "seconds": 5 },
{ "type": "flow", "mermaid": "flowchart LR\n A[Width] --> B{\"< 1440 px?\"}\n B -- yes --> C[Icons]:::changed", "seconds": 6 },
{ "type": "compare", "before": "before.png", "after": "after.png", "seconds": 5 },
{ "type": "clip", "heading": "Recorded at 1280 px", "src": "run.webm", "caption": "e2e: checkout-fit", "speed": 1.5, "maxSeconds": 12 },
{ "type": "key", "result": "../../review-key/331/result.json", "baseFails": true, "seconds": 7,
"rows": [{ "ok": true, "text": "`verify.sh` · 476 tests" }] },
{ "type": "end", "title": "Ready for review", "lines": ["PR: **github.com/…/pull/352**", "3 am: …"], "seconds": 3 }
]
}
シーンタイプ: title、bullets(items 最大4つ)、flow(mermaid、legend: false で凡例非表示)、compare(before、after、ラベル;layout: "stack" で縦並び、ツールバーなどの横長に)、clip(src .webm/.mp4、from/to 秒、speed、maxSeconds デフォルト20、crop {x, y, w, h} で録画のピクセル単位で重要部分を拡大;長さはファイルから取得)、key(result = keycheckのresult.jsonまたはオブジェクト;verdict、baseFails、claim、rows と count {value, total, label} で上書き — 例:8ケースを実行する1つのチェックは 8/8 と表示する方が分かりやすい)、checks(items に name、detail、ok)、end(title、lines)。すべてのシーンに heading、kicker、seconds を設定可能。変更にないものは省略 — バックエンド変更には compare や clip は不要。純粋なリファクタリングには key シーンで同値性のみを示す。
key シーンの左パネルには最大8行まで表示でき、レビューキーのチェック前に独自の rows を追加できるため、テストは各行に1つずつ("verify.sh · 476 tests"など)配置し、その後のchecks シーンには回さない。checks` シーンはレビューキーを表示する必要がない場合にのみ使用する。
表現の注意
キャプションは表示秒数内で読まれるため、すべての単語に意味を持たせる必要があります。視聴者をいら立たせたデモから学んだ3つのルール:
- 結果を述べよ、称賛するな。 判定スタンプと「key-reviewerによる独立検証済み」ですでにキー通過と検証者を示しています。「PASS、カンニングなし」や「完全検証済み」は作者が自分の宿題を採点しているように読めます。判定について余計なことは一切書かない。
- カウントラベルは名詞で:
checks pass、cases identical、tests。「fail」のような動詞をラベルに使うと「5/5」が逆に読まれる文になります — 「5件中5件が失敗」は変更が壊れているように聞こえますが、実際にはベースブランチが失敗している意味です。ベースが失敗することを伝えたい場合は、baseFails行を使用してください。これは自動的に適切な表現になります。 - 無駄な言葉を削除: 「successfully」「as expected」「this ensures that」、およびタイトルを言い換えただけの箇条書きはカット。レビュアーが「ええ、当然だよね」と思うような箇条書きは、箇条書きにする価値がありません。
3. レンダリング
node <このスキルのディレクトリ>/scripts/render-demo.mjs out/demo/<番号>/demo.json [--webm]
Chromiumで各シーンをフレーム単位で描画し(テキストは鮮明、ドロップフレームなし)、demo.mp4(H.264、Slack・GitHub・ブラウザでインライン再生)、demo.png(ポスター画像:フローまたはキーシーン)、および --webm オプションでVP9の demo.webm をエンコードします。ffmpegが必要で、プロジェクトからPlaywrightを使用するか、なければ ~/.cache/carnufex-showcase に一度インストールします。レンダリング時間は動画1秒あたり約1秒です。
送信前に確認: 各シーンからフレームを抽出し(ffmpeg -ss <時間> -i demo.mp4 -frames:v 1 f.png)、確認します。テキストの切れ、空のダイアグラム、ログイン画面のクリップなどがあれば修正して再レンダリングします。
4. 投稿
プロファイルの Notify に指定されたチャンネルに、ボットとして 投稿します。これにより、相手に実際の通知が届きます(Slackコネクタ経由で投稿すると本人からのメッセージ扱いになり、Slackは自分のメッセージを通知しません)。PRごとに1つのスレッド: デモがPRのスレッドを開始し、その後のCI、レビューラウンド、マージ、デプロイ、本番確認、ロールバックはすべてそのスレッドへの返信として投稿します(ship がそれらを投稿)。チャンネルには全リポジトリにわたって、PRごとに1行が表示されます。メッセージはファイルに書き込みます。メッセージは単独で意味をなす必要があり(Slack mrkdwn)、リポジトリ名で始めます:
*<リポジトリ>* · PR #<番号> · <タイトル> — ready for review
<PR URL>
• <変更内容、1行目>
• <2行目>
Review key (<種類>): *PASS*, checked independently: <判定結果から1行>
3 am: <シグナル>
node <このスキルのディレクトリ>/scripts/post-slack.mjs --channel <ID> --pr <PRのURL> --file out/demo/<番号>/demo.mp4 --title "<リポジトリ> PR #<番号>: <タイトル> (<秒数> s)" --comment-file out/demo/<番号>/message.md
node <このスキルのディレクトリ>/scripts/post-slack.mjs --channel <ID> --pr <PRのURL> --text-file update.md [--broadcast]
--pr はチャンネル内のPRのURLからスレッドを検索します(状態は保持しません):見つかればそのスレッドに投稿、見つからなければ新規スレッドを開始します。--text-file はファイルなしでメッセージを投稿します。--broadcast はスレッドの返信をチャンネルにも表示します(結果報告(本番稼働またはロールバック)に使用)。スレッドとパーマリンクが出力されます。ボットトークンは SLACK_BOT_TOKEN またはslack-channelプラグインの ~/.claude/channels/slack/.env から取得します。ボットはチャンネルに参加している必要があります(not_in_channel の場合:/invite @<ボット名>)。ボットがない場合は、Slackコネクタ(slack_get_file_upload_url → バイナリPOST → slack_complete_file_upload)にフォールバックし、通知が送信されないことを伝えます。
同じ3行のテキスト、Mermaidフローチャート、SlackリンクをPRの説明欄にも追加します(GitHubはMermaidを描画しますが、API経由でアップロードした動画は再生できません)。