前回、「データは揃いましたが、本番投入とアプリ側の対応はこれから」と書きました。この記事はその続編です。前編(データ収集編)はこちら。
その「これから」をやりました。個人開発している「まなびマップ」(親子で使う学校選びの地図ノート、https://manabi-map.app )の全国展開に向けて、AI サブエージェント約120本が集めた東日本13道県の学校データを、本番の PostgreSQL(Supabase)に投入する日です。結論から言うと、投入は無事に終わりました。ただし想定外が5連発。この記事はその検収と本番投入のログです。Claude Code のマルチエージェント運用の続編ですが、中身は泥臭いデータ検証の話です。
まず訂正から。前回の記事、数字が間違っていました
前回「1,294拠点」と書きました。正しくは 1,194 拠点です。
投入時に県別の count(*) を照合して発覚しました。間違い方が興味深くて、県別の内訳(北陸154、甲信越273、東北473、北海道294)は全部合っていた。足すと 1,194 なのに、報告書の合計欄だけ 1,294 になっていた。偏差値の件数も同じで、内訳の和は 451 なのに、合計だけ 551。どちらも、ちょうど 100 多い。
どこかのエージェントが合計を書くときに足し損ね、以降の報告が全部その数字を引用した、という流れだと見ています。人間の集計ミスとまったく同じ形。悔しいのは、データ本体の検査は4重にやったのに、「内訳と合計の検算」だけは誰もやっていなかったことです。指揮役の自分も、検収エージェントも、報告書の足し算を疑わなかった。
DB に入れれば count(*) は嘘をつきません。集計の最終検収は投入時の実測。これを先に言っておきます。
投入前の grep で、本番から33校消えていることが分かった
今回の作業には「既存の本番データへの疑い」の白黒付けも含まれていました。入試実績を集めていたエージェントが、「この学校たち、本番データに存在しなくないですか」という報告を残していたからです。
正本の SQL を grep してみたら、すぐ分かりました。あるブロックの見出しコメントは「相模原市 県立12校」。なのに、その下に並んでいる insert 文は横須賀・三浦・鎌倉の13校でした。担当エージェントの取り違えで、相模原の学校が丸ごと収録されていなかった。さらに学校名簿と全件突合すると、私立も18校足りない。合計33校です。学校選びの地図サービスで、慶應義塾や浅野クラスの有名校が検索しても出てこない状態が、公開から5日間続いていたことになります。
図にすると単純で、見出しと中身がずれていただけです。ただ、当時の検収はブロックの見出しと校数合計を見て通していた。中身の市区町村までは見ていなかった。今回の発見に DB 接続は不要で、grep とリストの突合だけで白黒が付きました。調査系のミスは、派手な照合よりまず grep です。
投入当日。エラーが3回、止めてくれた
migration、修正 SQL、13道県の順で流し始めてすぐ、学科を入れ替える update SQL が外部キー制約で止まりました。旧学科の行に偏差値データが20件ぶら下がっていて、こちらは cascade で一緒に消える前提でいた。実際の定義は restrict。DELETE ごと拒否です。トランザクションのおかげで中途半端には壊れず、旧学科の偏差値を先に消す SQL を1本挟んで解決しました。ここは事前に「ユーザーのお気に入りデータからの参照はゼロ」まで確認して安心しきっていた場所で、刺さったのは自前の推計値テーブルのほうでした。
次は宮城の入試実績で一意制約違反。掘ってみると、原因は自作の SQL 生成スクリプトの仕様でした。CSV の学科名が学校データと完全一致しないとき、警告を出さずに黙って NULL を入れる。学科改編前の旧名で書かれた行が2つとも NULL になり、同じ学校・同じ年度で衝突して、たまたまエラーになった。
たまたま、です。実際、先に投入した新潟には NULL の行が3件、音もなく入っていました。エラーで止まる失敗はありがたい。静かに壊れる失敗が一番高くつく。
上の図が今回の教訓の核心です。同じ「学科名の不一致」から出た NULL でも、行き先は3通りありました。制約違反で止まって発覚したもの(幸運)、静かに混入していたもの(実害)、そして千葉の30行のように「くくり募集で学科別の数字が公表されない」ための意図的な NULL(仕様)。ここで手を止めて、20都道県ぶんの CSV の校名と学科名を DB と機械突合しました。旧学科名の残存が9行(収録対象外として除去)、学科名がそもそも間違っていたのが2件。うち1件は「・」の有無、もう1件は20年以上前の学科改編に気づいていなかったもので、どちらも学校の公式サイトで現行名を確定して直しました。
学んだこと
- 集計は自己申告を信じない。内訳と合計の検算、最後は DB の count(*) との照合までを検収に含める
- エラーで止まるのは良い設計。今回の被害を防いだのは外部キー制約・一意制約・トランザクション、つまり DB の基本機能だった
- 一番怖いのは黙って NULL が入る系。生成スクリプトには「解決できなかったら警告」を足してから西日本に行く
- 本番に触る操作は1つの関門に集約する。直前にバックアップ、実行は人間の承認後。120本のエージェントの成果物も、この関門だけは全部通した
投入後、プレビューの地図には20都道県・2,589校が並びました。前回「地図はまだ半分です」と書きましたが、データの上では半分を超えました。アプリ側の検索対応とリリースはこれから。西日本には、今回できあがった検収装置を一式持って行きます。
たぶんまた、想定外は出ます。出る前提で、止まってくれる仕組みを増やしておきます。
このデータが載るサービス本体はこちらです。住所を入れると通える高校が地図に出て、気になる学校を家族でメモできる無料の学校選びノートです。中学生のお子さんがいる方はぜひ。
前編(サブエージェント120本でデータを集めた話)を読んでいない方はこちらからどうぞ。
※ ヘッダー画像とインフォグラフィックは AI(画像生成)で作成しています。
書いた人: ishizakahiroshi
群馬の北部で、保護猫2匹と暮らす、在宅エンジニア(何でも屋)
https://ishizakahiroshi.github.io/
https://github.com/ishizakahiroshi
X(業務委託・各種相談はこちら):
https://x.com/ishizakahiroshi
バックエンド・インフラ・AI連携まわりで、業務委託のご相談を受け付けています。フルリモートです。スポットや週2〜3時間からでも歓迎で、いろんな案件に携われたらうれしいです。こんな相談、歓迎です。



