開発eurekapu-nuxt4

eurekapu-nuxt4 全77ページ2カラム化 + Part 2 投資判断クイズ + 教科書 CH8-12 実装

朝イチ: Part 2 投資判断クイズの動作確認

まず昨日仕上げた Part 2 投資判断クイズ18ページが本当に動くか、Chrome DevTools を全ページに走らせた。結果は18ページ全部 HTTP 200、コンソールエラーゼロ。モバイル500px幅でも崩れないことを目視で確認した。

SVG が初期状態で「対応する図はありません」のプレースホルダーになっていて一瞬慌てたが、これは自分が前日に決めた仕様通り。回答するまで図を出さない設計で、回答後はマゼンタハイライトに切り替わる。ここは触らない。

TS型エラー 62件 → 0件

pnpm typecheck を走らせたら62件出てきた。1件は Part 2 由来だったが、リファクタの過程で既に消えていたので無視。

残りの構造を自分で眺めると、ほぼ2パターンに収束していた。

1件目は AnPerEmployeeHighlight 型の | null が原因で、ハンドラの分岐が網羅できないという指摘。型から | null を外すよう指示したら5件消えた。

56件は BS/PL 画面の同じパターンだと気づいた。

<div v-if="deltaPopups[key]">
  {{ deltaPopups[key].id }}  <!-- TS2532: Object is possibly 'undefined' -->
</div>

v-if でガードしているのに narrowing が効かない Vue + TS の既知パターン。1件ずつ書き換えるのは嫌なので、sed で deltaPopups[xxx].iddeltaPopups[xxx]!.id に一括置換してもらった。56件が一気に消えて、合計0件になった。

AnPerEmployee マゼンタハイライトで文字が消えるバグ

確認中に、ハイライト時のテキストが見えなくなる現象を画面で見つけた。ハイライト時にテキストすべてを #fff に塗っていて、白いボックスの中の白い文字が消滅していた。

該当箇所6つすべて #fff から #111 に戻すよう指示して、マゼンタ枠 + 黒文字の構成に直してもらった。これで読める。

全77ページの2カラム化

ここから本日のメインタスク。Part 2 の01ページで参考実装した2カラムレイアウトを、残り17ページに展開する方針を決めた。さらに practice-industry-quiz 系の5ページは別構造だったので、専用ラッパー PerQuizFigurePage を切って統一する設計に直した。

最終的に全77ページが3種類のラッパーに収まった。

  • QuizPage を直接使う通常ページ
  • InvestmentTopicPage(投資判断クイズ系の2カラム)
  • PerQuizFigurePage(per-quiz 図対応の2カラム)

スクロールspy: 「見えているクイズの図」を出す

自分の一言で設計が変わった瞬間がここ。画面を触りながら「Q3にスクロールした時、答える前でもQ3に対応する図が左側に出てほしい」と感じて、その場で要件として投げた。

これまでは「回答済みクイズのうち最新のもの」をハイライトする設計にしていたが、スクロール位置で動的に切り替える方式に作り直すことに決めた。

QuizPage にスクロール追跡を入れて、slot に2つの prop を渡す設計に変えてもらった。

<slot
  :visibleHighlight="currentVisibleHighlight"
  :isVisibleAnswered="answered[currentVisibleQuizId]"
/>

これで「Q3にスクロールしたらQ3の図」「答えるとマゼンタになる」が両立する。実装後に自分でスクロールしてみると、図が切り替わる挙動は思った以上に気持ちいい。

目次に Part 1 / Part 2 の境界

連番だけだと CH7 と CH8 が直結して見えて、Part の切れ目が消えていることに気づいた。セクションヘッダで「Part 1: 財務諸表の読み方」「Part 2: 投資判断」と区切るよう指示したら、構造が一目で分かるようになった。

Part 2 教科書 CH8-12 を派遣

5/14 の handoff では「CH8-12 は別フェーズの大きな塊」として別日扱いだったが、勢いで今日着手することに決めた。Part 1 と同じパターンで、CH8 をパイロットで先行させて、CH9-12 をサブエージェント並列で派遣する段取りを組んだ。

最初は4並列でサブエージェントを派遣したら、Anthropic API が 529 Overloaded を返して全クラッシュした。2並列 × 2セットに減らして再派遣したら、これは通った。

書籍データの扱いで一つ判断した。当初は計画段階で Turso DB の書籍知識(Market Hack 本ほか)を参照させていたが、章立てが Eurekapu の指示書と似通っていることに気づいて、表面的にコピーする危険があると感じた。

書籍DB参照は CH8 のリライト段階に移すことに決めて、必ず Eurekapu の文脈(個人投資家向け、日本の投資環境)に合わせ直してから書かせる方針に切り替えた。Codex アプリに「指示書§4 を Eurekapu 文脈に書き換える提案」を頼み、返ってきた提案を自分で確認・承認したうえで4章分(CH8-12 v2.0)を派遣した。

全章 HTTP 200 を確認、3つに分割してコミットした。

  • 実装ファイル
  • 指示書改訂(§4 リライト)
  • セキュリティ関連(後述)

Part 2 CH8-12 のレビュー計画書

書き上げた直後に質を担保したかったので、自分でレビュー計画書を起こした。観点は4つに絞った。

  • 各章が独立した読み物として読めるか
  • 数字のファクトチェック
  • ロジカル構成(前章を引きずらない・次章へ繋ぐ)
  • 日本語のAI臭除去

Codex に2回レビューを回した結果「致命的な指摘なし」まで到達した。最終的な実装は Codex アプリに担当させる方針に決めて、プロンプトを internal/ 配下に自分で保存しておいた。

EDINET APIキー漏洩の処理

夜にコミット履歴を眺めていたら、過去コミット d598c5f に EDINET の API キーが残っているのを自分で見つけてしまった。

すぐ EDINET の管理画面で revoke 済みを確認し、.gitignoresettings.local.json を追加するよう指示。Issue ファイルに経緯を自分で書いて「解決済み」のステータスで残した。今後の自分への踏み台として残しておく。

今日の振り返り

  • 型エラー62件は、自分が2パターンに収束していると気づいて sed 一括置換に倒した。6文字書き換えるだけで0になった
  • 4並列サブエージェント派遣は API Overloaded のリスクがあると体感した。書籍関連のような長文タスクは2並列が安全と判断した
  • 書籍DB を「計画段階で読ませる」と章立てが寄ってしまうことに気づいた。「リライト段階で読ませる」が正解と決めた
  • スクロール位置で図を切り替える設計は、自分が画面を触っていて出した一言から生まれた。実装後の体感は確かに気持ちいい
  • API キー漏洩は即 revoke + .gitignore + Issue 記録の3点セットで動くと自分のルールに固めた

明日やること

  • Part 2 CH8-12 v2.0 の最終チェックを Codex アプリに依頼
  • レビュー観点(独立読み・ファクト・ロジカル・AI臭)を全章で再確認
  • 書籍DB 参照ログを memo に残し、どの章でどの本を参照したかを追えるようにする