学習ゲートの全リポジトリ展開とSVG図解のNG/OK表現改善

開発eurekapu-nuxt4

学習ゲートの全リポジトリ展開とSVG図解のNG/OK表現改善

今日は2つの糸が同時に進んだ日だった。ひとつはeurekapu-nuxt4のデプロイ後コミットで見つけた学習ゲートの穴、もうひとつはsvg-diagramスキルのアップデートを反映する図解の作り直し。

学習ゲートが「起動しません」と言われて固まった

朝、eurekapu-nuxt4のdraft講座素材の露出をデプロイスクリプトで回収し、本番に反映した。仕上げにコミットを頼んだら、返ってきたメッセージに目を疑った。「core.hooksPathがローカルで.git/hooksを指しており、pre-commit実体がないため学習ゲートは起動せず、スラッシュコマンド不要でそのまま通った」。

mdx-playgroundだけでなく全プロジェクトで/learnを走らせたくて、わざわざグローバル設定(core.hooksPath = ~/.claude/githooks)を仕込んだはずだった。それなのに、なぜeurekapu-nuxt4だけ素通りしたのか。原因調査をClaude Codeに委ねた。

判明した構造はこうだった。

  • eurekapu-nuxt4はSVG/PNG/JPGを含む3,102ファイルをGit LFSで管理している
  • Git LFSを導入した際、git lfs installがリポジトリローカルのcore.hooksPath.git/hooksに書き換えていた
  • core.hooksPathは1つの値しか持てないので、これがグローバル設定を丸ごと上書きしていた
  • 上書き先の.git/hooksには学習ゲートのpre-commit実体が存在しなかった

LFSのフック(post-checkout / post-commit / pre-push等)は必要なので.git/hooks自体は残す必要がある。そこで、.git/hooks/pre-commitにグローバル学習ゲート本体へ委譲する薄いラッパーを新設する方針にした。

#!/bin/sh
export LEARN_GATE_DELEGATED=1
exec "$HOME/.claude/githooks/pre-commit" "$@"

この案をCodex(GPT-5.5)にレビューしてもらったら、致命的な指摘が返ってきた。再帰防止のガードをラッパー側のexit 0に置くと、LEARN_GATE_DELEGATEDという環境変数が何かの拍子に外部環境へ紛れ込んだ場合、ゲート全体が音もなく素通りする危険がある、という指摘だった。ガードはラッパー側ではなく、グローバル本体が「リポジトリ自身のpre-commitを呼び戻す」条件分岐の側に移してもらった。

グローバル本体(~/.claude/githooks/pre-commit)を直接編集させようとしたら、保護対象ファイルとして自動編集が一度弾かれた。「先ほどこの変更を承認せずCodexレビューに委ねた経緯があるので、レビュー結果を見てから許可プロンプトで判断してほしい」という理由で、これは意図通りの安全機構だと分かって手動で許可した。

修正後、受領証なしのコミットを試して、①ゲートが起動して🧠 未学習の変更がありますでブロックされるか、②無限再帰せず即座に終わるか、の2点を検証した。両方クリアし、LEARN_SKIP=1のバイパスも生きていることを確認した。

ここで気になって聞いた。「再クローンしたらこの修正は残るのか」「pushできないのか」。答えは両方ノーだった。.git/hooksの中身もローカルのgit config.git/配下でリポジトリの管理対象外、つまりpushできず、再クローンすれば消える。dotfilesと違って、この手の設定はマシンごとに毎回仕込み直しになる、という当たり前の事実に今更気づいた。

「Git_Repo配下のリポジトリなら基本的に全部/learnがかかっていると思っていいか」と確認したところ、実際に約160リポジトリを全部スキャンしてもらった。overrideがあったのは5つだけ。mdx-playground(自前のトラッキング済み.githooksで意図的)とeurekapu-nuxt4(今回対処済み)以外の3つ(AutoHotkey / chrome-extension-MF / sokuroku)は、コンテナ作業の残骸でcore.hooksPath/workspace/.git/hooksという存在しないパスを指していた。LFSは使っていないので、こちらはoverrideを外すだけでグローバル設定に戻した。これで約160リポジトリ全部が学習ゲートON状態になった。

書き捨てメモではなく~/.claude/rules/learn-gate-hooks.mdとしてルール化した。再クローン時に同じ穴に落ちないための検出コマンドと対処手順を残しておいた。

その後、~/.claude自体のdotfilesリポジトリでルールファイルをコミットした際に「今回は学習ゲートが走らなかった理由は何か」と聞き返した。答えは「スラッシュコマンドそのものだから特別扱いされた」ではなく、単にdotfiles設定の同期であることを理由にLEARN_SKIP=1で明示的にスキップしただけだった。ゲート自体はちゃんと起動していたと分かって、これ以降のコミットは基本的に毎回ゲートに引っかかる、という運用の輪郭がようやく固まった。

svg-diagramスキルの更新をコース自身の図解に反映する

svg-diagramスキルの解説コース内で、NG/OKの対比を素朴な2カラムテーブルで表現していた箇所が気になった。テーブルだと視線がカラム間を往復するだけで、どちらがダメでどちらが良いのか一目で入ってこない。×ボタン(赤)とチェックマーク(緑)を使った、もっと明示的な対比表示に作り直したいと伝えた。

対象のpurposeページ(「図は手段であって目的でない」「根無し図表」)にあった3つのテーブルを、赤丸×・緑丸✓のヘッダーバッジ付きカードに置き換えてもらい、実機のスクリーンショットで見切れ・重なりがないことを確認した。

ところが、これで終わりではなかった。「NG/OK」という文字列だけを検索対象にしていたため、<th>NG</th><th>直し方</th>という別の見出しのテーブルが検索から漏れていた。指摘したところ、NG関連のテーブル全部を洗い出し直してもらい、残り2箇所も同じカード形式に作り直した。

ここまでの改修を土台に、コース全体93セクションへの図解追加を9並列のエージェントに任せるワークフローを起動した。開始時37個だったSVGファイルは124個まで増え、8ファイルは完走したが、SkillBasicsだけがAPIエラーで停止していた。単発のエージェントを追加で走らせて完遂させた。

完了報告のあと、今度は「図解を追加したページで、その下の元のテーブルや文章と内容が重複している」という指摘を入れた。9ファイル・96セクションを見直すワークフローを別途起動してもらい、9箇所の重複コンテンツを削除してもらった。

さらに細かい指摘も入れた。ヘッダーに×/✓バッジを置いたのに、各行のレコード部分にも同じ記号を3回分繰り返して入れていた。ヘッダーで判別できるのだから行ごとの記号は不要だと伝え、CSS側だけの修正で各行の記号を消してもらった。

財務数値ケースのデリバティブ解説ページに反映する

svg-diagramスキル自体がさらにアップデートされた(12カラムグリッド・塗りのみの区切り・マゼンタ単色強調・角丸やストロークの禁止)ので、まず財務数値ケースの教材にあるデリバティブ解説ページの対比図SVGを新ルールで作り直してもらった。

描画確認の途中でChrome DevTools MCPの接続が切れ、taskkill //IM chrome.exe //Fを実行して開いていた通常のChromeウィンドウを全部落としてしまった。確認なしの操作だったので、以降はデバッグ用の別プロファイルだけを使うようにしてもらった。

作り直した図自体は見切れも重なりもなく描画できたが、別の指摘が入った。「まとめ」リストが読みづらいという画像付きの指摘で、原因を追うと<strong>タグへのCSSセレクタが犯人だった。

/* Before: liの中の全<strong>に見出しスタイルが乗る */
.topics-list li :deep(strong) { display: block; color: magenta; margin-left: -1em; }

/* After: 先頭(番号ラベル)だけに限定 */
.topics-list li :deep(strong:first-child) { display: block; color: magenta; margin-left: -1em; }

先頭の番号ラベル用と、文中の強調語用の2つの<strong>が同じセレクタに引っかかり、文中の強調語まで無理やり改行・インデントされて文章がぶつ切りになっていた。セレクタを:first-childに絞って直してもらった。

この3点セット(SVG再設計・<strong>セレクタのバグ防御・該当ページのみBS/PLボックス図の追加)を、似た構成の教材ページ21本のうち20本にワークフローで展開した。各ページを1エージェントに実装させ、実装結果を鵜呑みにせず別のエージェントに独立検証させる2段構成にした。

検証で1本だけ不合格になった。ストックオプション解説ページで、貸借の恒等式が崩れていた。資産側「変動なし」に対して、純資産側が「利益剰余金の減少」と「新株予約権・資本金等の増加」を1つの科目にまとめてしまい、金額が合っていなかった。2列に分けて内訳を分離し、資産側の「変動なし」と釣り合う形に直してもらった。

一連のSVG改修は、これで終わりではなく次の作業に続く。20ページ分のワークフロー結果を、今度は自分の目で1ページずつレビューしていくことにした。図解が記事の内容とちゃんと対応しているか、スライドの主張とズレていないかを見ていき、ズレていればskill本体(~/.claude/skills/svg-diagram/)側を直接直してもらう運用にする。この作業はセッションを分けて進めるため、ここまでの経緯と次にやることを計画書として残しておいた。

今日の学び

  • core.hooksPathは1つの値しか持てない。LFSやコンテナ作業が黙って上書きすることがあり、意図した設定が全リポジトリに効いているとは限らない
  • .git/hooksもローカルのgit configもpushできない。再クローンすれば消えるので、恒久対策にするならルールとして残し、再設置の手順ごと書いておく必要がある
  • ヘッダーで示せる情報を行ごとに繰り返さない。バッジ1つで十分伝わるところに記号を重ねると、かえって読みにくくなる
  • CSSセレクタは「同じタグ内の役割違い」を見落としやすい。<strong>が2つある行で1つ目の意図だけを想定してセレクタを書くと、2つ目が事故る
  • 図解を追加しても、その下の表や文章が同じ内容の焼き直しなら意味がない。図解を足したら重複チェックまでセットで見直す