計画書の中で判断を返す — ターミナルの選択肢をやめてHTMLに3択ボタンを埋めた
計画書の中で判断を返す — ターミナルの選択肢をやめてHTMLに3択ボタンを埋めた
我流のまま200記事書いてきた
タイトルもディスクリプションも、記事を書くたびに手で埋めてきた。その場で思いついた言い回しを入れて、次の記事ではまた別の言い回しを入れる。サイト全体で何を取りに行くかを決めたことは、一度もない。
WordPressから移したサイトの本番切替が片付いた朝、そのまま次を投げた。全ページのタイトル・ディスクリプション、それにAIボットへの応答方針まで含めて一度レビューし、改善点を洗い出したうえで方向性を決めて、直し方の計画まで立てておいてほしい、と。切替そのものの記録は別に残してある。
「全てのページで」と言い添えた。203記事ある。
3本のレビューが同じところを指した
記事メタのレビューは6バッチに分けて回させた。並行して、観点を絞った専門レビューを3本、独立に走らせている。途中でセッション上限に当たって専門3本が落ちたので、完了分のキャッシュを使い回して失敗した3件だけ再実行させた。
戻ってきた結果は、203記事全件から60のパターンと60本のワーストページ。抽出したデータに引用符が混ざって集計が壊れたので、ワンライナーをやめてスクリプトをファイルに書かせ直している。
数えさせて目が覚めたのは、タイトルの頭に付けてきた定型句が27種類に分裂していたことだった。自分では同じ型で書いてきたつもりでいた。画像が主役の記事の弱さも、alt属性の実態も、数字で並ぶと言い訳が効かない。
独立に走らせた3本のレビューが、そろって同じ点を最重要に挙げてきた。3人が別々に見て同じ場所を指すなら、それは好みの問題ではない。
計画書はできた。判断が4件残った
計画書を書かせて、要点を図解させた。図3で本文テキストがカードの幅を越えて右のラベルに重なっていたので直させ、描画を確認してからコミットさせている。
残ったのは、自分が決めないと先に進めない項目が4件。ここでいつもの選択肢が出そうになった。ターミナルに並ぶ、あの矢印キーで選ぶやつだ。
そこで止めた。
ClaudeCode内でもインタラクティブにできるやつあるじゃないですか。あれだと何を聞かれてるかの前提が分かんなかったりするんで、やっぱこのHTMLで答えさせる方が私にとってはちょっとやりやすいかなって感じしてるんですよ。前提も読みやすいし。
判断の前提は計画書の本文にある。なぜその判断が要るのか、何と何を天秤にかけるのか、選び損ねると何が起きるのか。それを読んだ直後にボタンがあれば、読んだ流れのまま押せる。ターミナルの選択肢は、本文を読みながら選ぶことができない。画面の外にある文章を思い出しながら矢印キーを叩くことになる。
計画書のHTMLの中に、A・B・Cのボタンを置いてほしい。できれば3択。推奨はいつもどおり明示する。全部選んだら送信する。一度選んだあとで変えることもある。そう伝えて、作らせた。
作った仕組み
再利用できる形にさせた。計画書ごとに手で組み立てるのでは、次の計画書で使われない。
計画書のMarkdown側は、判断項目の説明を書いた直後に空のdivを1行置くだけにした。pandocのgfmはこの生HTMLをそのまま通す。
### 5-1. AIクローラー方針 — 学習用クロールを許可するか
(判断の前提・背景・注意点をここに書く)
<div data-decision="1"></div>
選択肢そのものは計画書に書かない。同じベース名のJSONに分けた。
{
"id": "1",
"question": "AIクローラーに学習用クロールを許可しますか?",
"options": [
{ "key": "B", "label": "回答は許可・学習は拒否", "detail": "…", "recommended": true },
{ "key": "A", "label": "全面歓迎", "detail": "…" },
{ "key": "C", "label": "全面ブロック", "detail": "…" }
]
}
配信は使い捨てのローカルサーバーにさせた。pandocで作ったHTMLにフォームの資材を注入して 127.0.0.1 にだけ出す。Node標準ライブラリだけで書かせたので、インストールするものはない。計画書と同じディレクトリの画像やSVGも一緒に配ってくれるので、埋め込み忘れた図が抜け落ちることもない。
送信の作法はこう決めた。
- 選択は何度でも変えられる。送信するまで確定しない
- 全項目を選ぶまで送信ボタンは押せない。未回答があるときは、その項目へ飛ぶボタンが出る
- 送信は1回のPOSTで全項目まとめて。項目ごとにバラバラに飛ぶことはない
- 各項目に自由記述欄がある
- 受け取ったらJSONに書き出して、サーバーは自分で終了する
サーバーが立ったあと、ブラウザで開いてスクリーンショットを撮らせ、4項目×3択が全部描画されていることを確認させてから案内させている。「起動しました」だけで渡されても、押せる状態かどうかはこちらには分からない。
3択にする理由と、推奨を1つ置く理由
選択肢の数は3つを基本にさせた。2択は逃げ道がなく、どちらも嫌なときに答えようがない。4択以上は比べる負担が急に増える。3つ目には「保留してもう一段調べる」「片方だけ先に試す」のような中間案がだいたい置ける。
推奨は1つだけ付けさせた。全部フラットに並べられると、こちらは全部の前提を自力で比較することになる。それは判断のコストを丸ごとこちらに渡しているのと同じだ。推奨があれば「その線でいいか」を検討するところから始められる。
説明文には「選ぶと何がどうなるか」を書かせた。用語の定義ではなく結果を書く。利点だけでなく欠点も併記させる。
最初の版は、本文に比較表があり、ボタンにも同じ比較が入っていた。同じものを2回読まされる。ボタン側に一本化して、本文は「なぜ判断が要るか」だけを持つように整理させた。
テストは別ポート・別出力先で
本番の出力先に向けてテスト送信させない、という約束をここで決めた。回答が1回届いた時点でサーバーは終わるので、テストで潰すと本物の回答を受け取れなくなる。別ポート・別ファイルのテスト用インスタンスで、選択・選び直し・未回答カウンタ・送信までを一周させ、テストで出た成果物を消してから本番用を起動させた。
自由記述欄から設計指示が返ってきた
4件の回答は10時55分にJSONで届いた。AIクローラーの件は、学習用のクロールを許可するかを3択から選んで返している。
面白かったのは4件目だ。用意された選択肢のうち「全記事で移す」を選んだうえで、コメント欄にこう書いた。代わりにCTAを置いてほしい、PCは目次の下、モバイルは記事の末尾、文言は「この記事を書いた人」。
選択肢のどこにも書いていない指示だ。ボタンだけの仕組みだったら、この配置指示は次の往復まで出てこなかった。選ぶという行為が、選択肢に収まりきらない条件を引きずり出してくる。自由記述欄は飾りではなかった。
だから受信JSONの comment は必ず読ませる、とルールに明記させた。
1プロジェクト限りにしない
一度使って、その場で決めた。この運用は全プロジェクトでやる。
WordPress移行の計画書のためだけに作ったツールとして置いておくと、次に別のリポジトリで計画書を書かせたとき、また矢印キーの選択肢が出てくる。仕組みが手元にあることを、そのときの自分は思い出さない。
ユーザーレベルのルールに昇格させた。判断が必要な項目が2件以上ある計画書では、必ずこの方式を使う。判断が1件でも、技術的な兼ね合いや不可逆な操作の方式選択のように前提の理解が要るなら使ってよい。逆に「今すぐデプロイするか、後にするか」程度の、前提の説明が要らない二択はターミナルのままでいい。
ツール本体4ファイルと運用ルール、それに設定ファイルへのポインタを合わせて8ファイル783行でコミットさせた。ついでに未コミットのまま残っていた計画書プレビューまわりの資材も一緒に入っている。
学びメモ
- 判断を求める場所は、前提が書いてある場所と同じであるべき。前提と選択肢が別の画面に分かれていると、こちらは記憶を頼りに選ぶことになる。計画書の本文の直下にボタンがあるだけで、読む→選ぶが1つの流れになる
- 選択肢は3つ、推奨は1つ。フラットな並べ方は親切に見えて、判断のコストを全部こちらに渡している
- 自由記述欄は保険ではなく本命の入口。選択肢に無い設計指示が実際にそこから返ってきた。回答を受け取る側は、選んだキーだけ見て済ませてはいけない
- 一度きりの受信で終わるサーバーは、テスト送信で簡単に潰せる。検証は別ポート・別出力先で回す
- 便利だと思った運用は、その場でユーザーレベルのルールに上げる。プロジェクトのローカルに置いた時点で、次に思い出す確率が大きく下がる