• #miller-column
  • #migration
  • #codex-review
  • #sub-agent
  • #vitest
  • #eurekapu
開発eurekapu-nuxt4メモ

会計入門コンテンツのMiller Column移行

旧プロジェクトに眠っていた会計入門編(全7パート+補足+目次+概要の計10ページ)を、Miller Column Layoutへ一気に載せ替えた。朝にCodexへ計画を投げたら致命的指摘が3つ返ってきて計画を書き直すところから始まり、サブエージェント7本を並べて変換を走らせ、Chrome DevToolsで全ページを開いてUI問題を4つ潰し、テストを書いてまたCodexに叩かれる――そのサイクルを1日で2周回した。

計画立案とCodexレビュー

初回計画

移行対象の10ページを洗い出し、6フェーズの実装計画を立てた。

  • Phase 0: 画像アセットコピー
  • Phase 1: TOCデータ作成
  • Phase 2-3: 各パートのMillerChapterデータ変換(サブエージェント並行)
  • Phase 4: allMillerChapters登録
  • Phase 5: topics.ts更新
  • Phase 6: リダイレクト設定

Codex初回レビュー → 致命的指摘3点

codex execで計画をレビューにかけたところ、3つの致命的な指摘が返ってきた。

  1. 画像パスのハードコード: アセットコピー後のパス解決が未定義
  2. リダイレクト設定の抜け: 旧URLからのリダイレクトルールが不完全
  3. TOCとMillerChapterの整合性検証がない: データ変換後にTOCのエントリとMillerChapterの対応を確認するステップが欠落

3点とも計画を修正し、再レビューを実行。

Codex再レビュー → 追加2点

codex exec resume --lastで更新後の計画を再度レビュー。追加で2点の指摘。

  1. サブエージェント失敗時のリカバリ手順がない
  2. Phase間の依存関係が暗黙的 → 明示的な前提条件を追記

軽微な方は無視し、リカバリ手順のみ追記してから実装に入った。

実装: サブエージェント並行変換

Phase 0-1: 画像とTOC

画像アセットを旧プロジェクトからコピーし、TOCデータを手動で作成。10ページ分のメタ情報(タイトル、スラッグ、順序)を定義した。

Phase 2-3: 7つのサブエージェントで並行変換

Part 2〜7 + 補足の計7ファイルについて、サブエージェントを並行起動してMillerChapterデータに変換した。各サブエージェントは旧プロジェクトのMDXファイルを読み取り、Miller Column用のデータ構造に変換する同一のタスクを実行する。

並行実行によって、逐次処理なら30分以上かかる変換が数分で完了した。

Phase 4-6: 登録・更新・リダイレクト

  • allMillerChaptersに10ページ分を登録
  • topics.tsにトピックエントリを追加
  • 旧URLパターンからのリダイレクト設定

Chrome DevToolsで表示確認 → UI問題4件

全ページをChrome DevToolsで開いて表示を確認したところ、4つのUI問題が見つかった。

1. チャプターが1個しかない場合の列省略ロジック

Miller Columnは通常3列(セクション → チャプター → トピック)で構成するが、チャプターが1個しかないセクションでは中央の列が無駄に場所を取る。noChapterColフラグの判定ロジックを修正して、チャプターが1個の場合は列を省略し2列表示に切り替えるようにした。

2. 補足と演習問題の入れ子構造

補足コンテンツと「まとめ練習問題」がTOCデータ上で入れ子になっていた。本来は並列の関係なので、データ構造を修正して同一階層に並べた。

3. ドットナビゲーションのサイズ不統一

ページ内ナビゲーションのドットインジケーターが、ページによってサイズが異なっていた。CSSを統一して全ページで同一サイズに揃えた。

4. 演習問題のTOCインデックス除外

「まとめ-仕分け演習問題」がTOCのインデックスに表示されていたが、これは演習用のページなのでインデックスから除外した。

テスト追加と整合性検証

データ整合性テスト

移行した10ページ分のMillerChapterデータが正しい構造を持っているか検証するユニットテストを追加した。

  • 各チャプターの必須フィールド存在チェック
  • スラッグの一意性検証
  • 順序番号の連続性チェック

TOC-MillerChapter整合性チェック

TOCに定義されたエントリと、実際に存在するMillerChapterデータの対応を検証するテストを追加。

初回実装では「TOCに定義されているがMillerChapterが存在しない」ケースのみチェックしていた。Codexレビューで「片方向チェックでは不十分」と指摘を受け、逆方向(MillerChapterは存在するがTOCに登録されていない)も検証する双方向チェックに修正した。

// 片方向 → 双方向に修正
// TOC → MillerChapter の存在チェック
// MillerChapter → TOC の登録チェック(追加)

buildRangesのリファクタリング

テスト追加の過程で、buildRanges関数がletpushで状態を変更する手続き型のコードだったので、reduceを使った関数型に書き換えた。

今日の学び

  • Codexレビューは2回回す価値がある。初回で致命的な漏れを3つ潰し、修正後に再度かけたら別の観点から2つ出てきた。1回で満足せず、修正後にresume --lastでもう一度レビューを通す運用が定着してきた
  • サブエージェント並行起動はデータ変換に向いている。同一構造のファイルを同じルールで変換するタスクは、7並列で走らせても品質が安定する。逐次なら30分かかる変換が、並列で数分で揃った
  • Chrome DevToolsで全ページ舐めるのは省略できない。データ上は正しくても、列省略ロジックや入れ子構造の問題は画面を開いて初めて目に飛び込んでくる。特にMiller Columnは列数が動的に変わるので、エッジケースが表示で初めて露出する
  • 整合性テストは最初から双方向で書く。「AにあってBにない」だけでなく「BにあってAにない」も同時にチェックしないと、片方の追加漏れを見逃す。Codexに指摘されるまで気づかなかった

振り返り

計画を書く、Codexに投げる、指摘を受けて直す、サブエージェントを並べる、画面を開いて目で確かめる、テストを書く、またCodexに投げる。このループが2周回って、夕方にはMiller Column上で会計入門編の全ページが並んでいた。

人間がやったのは計画の判断とUI目視だけで、変換の実作業はサブエージェントが、品質チェックはCodexとテストが担った。この分業パターンは他のコンテンツ移行でもそのまま使える。