gogen-eitango Phase 4b・4d: アトラス3,859語の例文画像をCodexループで量産、並列数の飽和点を実測した日
gogen-eitango Phase 4b・4d: アトラス3,859語の例文画像をCodexループで量産、並列数の飽和点を実測した日
朝の積み残し確認から始めて、夜21時48分にOpenAI Codexの週次枠が100%に到達するまで、一日まるごと画像量産に付き合った。語源英単語講座のPhase 4b、アトラス3,859語の例文画像生成だ。画像は1枚あたり約2分かかる。なら並列数を上げれば、その分だけ速く終わるに違いない。そう思って一日中ノブを回し続けた。
朝: Phase 4a を締めてから 4b の方針決め
朝イチで「昨日の積み残しを教えて」と投げた。Phase 4a(例文3,859語の生成)は完走・コミット済みで、残りは5%目視検収・ドキュメント整合・Phase 4b着手の3つ。あわせて、古い再開プロンプトを使うと量産を再実行してしまう危険への対処として、昨日の進捗メモの前半に失効注記を付けさせた。
検収220件は自分で見るつもりでシートだけ作らせたが、途中で「ごめん、それはあなたが確認して」と任せ直した。レビュアー6体を並列で立てて220件を検収させ、結果は ok 204 / NG 16(誤検知0)。16件の修正と再エクスポートまで済んで、Phase 4a はクローズ。学習ゲートは正規の LEARN_SKIP で通し、本番デプロイと実ブラウザ確認まで走らせて、講座は公開状態になった。
ここで自分の理解が一つ曖昧なことに気づいた。「アトラス語って何でしたっけ」。確認させると、一般用語ではなく、元の教材の表パートの名前から取った講座内だけの呼び名だという。自分の講座の区分名を自分が忘れていた。
呼び名を思い出したところで、4b の進め方を決めた。OpenAI Codex を再帰ループで回し、レートリミットが来るまで画像を出力し続ける。前フェーズで確立した運用の流用だ。セッションを切り替えるため、引き継ぎプロンプトを出させた。
パイロット20枚 → マゼンタ強調 → 量産承認
昼のセッションで 4b を正式に開始。形式ゲートのユニットテスト9件を足してから、パイロット20語を3並列で生成させた。1枚あたり1.5〜2分。20枚すべて成功したので、検収シートをChromeで開かせて目視した(ブラウザ拡張が file:// を開けず、リポジトリを配信する小さな静的サーバーを立てさせる一手間を挟んだ)。
シートを眺めて注文を一つ。例文のどの単語が対象なのか分かりづらいので、見出し語をマゼンタで強調させた。アプリ側の既存ハイライトロジックの流用で済んだ。画像の雰囲気は問題なし。「100枚単位で区切って、途中で切りやすく」とだけ条件を付けて量産ループを承認した。1日では終わらない前提だ。
visual_spec の生成は10エージェントの波状投入で回り、パイロットを除く3,839語が全量揃った。ここから画像の量産に入った。
「まだ67枚?」——並列数のノブを回し続けた午後
量産開始からしばらくして進捗を聞くと、アトラス3,859枚中 67枚。6並列で約140枚/時のペースだという。140枚/時で割り算すると27時間超。意外と遅い。「並列数ってもっと上げられますか?」
ボトルネックは1枚約2分という生成時間そのものだから、並列数にはほぼ線形で効くはず、という読みが返ってきた。まず8並列(理論240枚/時)。Codexのレート制限が寛容なのは体感で知っていたので、12並列、24並列と強気に上げた。
同時49本前後で429(同時実行数の上限)が散発し始めた。ただし429を踏んだジョブは自動で pending に戻り、数秒後に別のランナーが拾い直す。設計どおりの自己回復で、実害はランナー1本がそのチャンクを早退するだけ。週次枠は「使い切っていい」と伝えて、40並列まで全開にした。
ところが40並列で異変が出た。10分前後で回るはずのチャンクが、34分経っても終わらない。実態を調べさせると、旧ランナーとの併走で同時60本を超えた瞬間にCodex側で処理遅延型の飽和が起きていて、スループットは630枚/時どころか120枚/時まで落ちていた。
並列は線形に効く。その読みが、ここで崩れた。速くするつもりで踏み込んだアクセルが、ブレーキとして働いていた。
40並列のドライバーを止め、在庫ランナーが掃けるのを待って24並列で立て直した。定常24並列はチャンク110枚を27分、約245枚/時。以後は27分ごとにチャンク完了の通知が届く安定運転に入った。おまけの学びもあった。ハーネス上でバックグラウンドタスクを止めても実プロセスは死んでおらず、40並列ドライバーはタスク表示が消えた後も次のチャンクを投入しようとしていた。最後はPIDを特定して直接killした。
使用率メーターと一緒に夜まで
並列数と同時に見ていたのが週次枠の使用率で、15時台に11%だったメーターが約40%/時のペースで削れていく。途中、自分が見ているCodexの画面は「残り96%」なのにモニタの数字と食い違う場面があり、ログのlimit種別とリセット時刻を突き合わせさせた。使用率モニタ自体にも罠があって、起動直後のセッションが0.0%を記録して実勢を上書きするので、直近8セッションの最大値方式に張り替えている。
定常運転に入ってからは、27分前後の周期でチャンクが刻まれていった。
- チャンク1: 110枚を27分(約245枚/時)
- チャンク2: 約110枚を17分(終端で429が16秒間隔に見えたのは連鎖ではなくランナーの自然収束だった)
- チャンク3: 110枚を25分 / チャンク4: 102枚を28分(429増加でやや減速)
- 以降チャンク10まで26〜28分周期で安定。429は各チャンク1〜6件の散発で、ジョブの取りこぼしは終日0件
21時ごろ、枠が尽きる前に一つ試させた。Codexの設定画面に週次リミットのリセットボタンがあるはずだから、押せるか見てほしい——リセットできるチケットを持っているつもりだったのだ。結果、手動リセットのボタンはどこにも存在せず、「クレジットの追加」は購入フローだった。購入画面が開いたところで止めさせた。
使用率90%(20:58)、97%(21:28)、そして21:48に100%。チャンク11の途中で429が十数秒間隔の連鎖に変わり、ランナーが1本ずつ離脱していった。限界まで絞り出して、Day 1 はチャンク10完了時点でアトラス約1,840枚(47.8%)。締め処理として、JSONの再エクスポート(imagePathの反映)、R2への同期(700枚前後を10並列アップロード)、夜間向けのモニタ静音化まで済ませた。ドライバーは30分ごとの自動リトライ待機に入っている。
Phase 4d: 表示ページは別セッションに切り出した
量産の合間に「この画像、どこのページで表示されるんでしたっけ」と聞いたら、表示ページはまだ存在しないという。それが Phase 4d。量産監視と混ぜたくなかったので別セッションに切り出すことにして、4b側にそっち向きのプロンプトを書かせた。画像がまだない語はプレースホルダーでいい、という条件付きで。
4dセッションでは、アトラス3,859語を59モジュール別に表示するページ群を実装させた。目次ページの検索、アンカー遷移のハイライト、スティッキー絞り込みバーにカード上端が隠れる問題の scroll-margin-top 修正、モバイル390pxのエミュレーション確認、ユニットテスト2本。既存のコース目次には、18章のカードを無傷のままアトラスへの導線だけが足されていることも確認した。
途中でClaude側のセッション上限に当たり、アカウントを切り替えて続行する一幕も挟んだ。今日はCodexとClaudeの両方でリミットの表示を見たことになる。
2セッションの分担は、思ったよりきれいに閉じた。アトラスのJSONは画像生成前にエクスポートしたもので全語 imagePath=null。4b側で再エクスポートして生成済み900枚分のパスを埋めてから、サブエージェントにChromeの実機検証を出した。「画像あり」と「プレースホルダー」の両方を同時に検証できて、全6項目PASS。画像が増えたら4b側が再エクスポートで埋めていく分担がそのまま運用になる。
計画書に Phase 4d 完了のチェックが入っていることもディスク上で確認した(「YouTubeの方って更新してくれてますか?」と口が滑って、計画書のことを聞いたオチ付きで)。4bの進捗記録も memo/2026-07-17/gogen-4b-pilot.md に追記させて、次のセッションが同じ現在地から再開できるようにしてある。
学び
- 「並列数は線形に効く」が成り立つのは飽和点まで。同時60本超で処理遅延型の飽和が起き、630枚/時が120枚/時に落ちた。上限は理屈ではなく実測でしか分からない
- 429対策は「ジョブを失わない」が肝。踏んだら即 pending に戻して別ランナーが拾う自己回復にしておくと、429の連鎖はそのまま上限到達の検知器になる
- ハーネス上のタスクkillは実プロセスを殺せないことがある。止めたつもりのドライバーが裏で生きていないか、PIDで実態を確認する
- 検収シートの「対象単語をマゼンタ強調」のような一手間が、目視の速度を決める
- レートリミットは敵ではなく区切り。100枚チャンク+自動リトライにしておけば「限界まで走らせて寝る」ができる
次にやること
- 週次枠の回復後、24並列の量産ループを再開する(残り約2,000枚。ドライバーは30分ごとに自動リトライ中)
- 生成が進んだらJSONを再エクスポートして、4dページのプレースホルダーを実画像に置き換える
- Phase 4c(SM-2間隔反復)は未着手のまま。4b完走後に着手を判断する
リセットボタンは、存在しなかった。残り約2,000枚を今週中に詰めるならクレジットを買い足すしかない。30分ごとの自動リトライに任せて枠の回復を待つか、財布を開くか——それは明日の自分が決める。