テストが民法の誤りを捕まえた ― AI駆動で相続計算ツールを13分で公開

AI
B!

「AIに書かせたら速い」は、もう珍しい話ではありません。問題は、速く出てきたコードが正しいと誰がどう確かめたのかのほうです。とくに、法令や料金表や業務規程のように「条件分岐がそのまま仕様になる」題材では、AIはもっともらしいが間違っているコードを平気で書きます。しかもそれは、読んだだけでは正しく見えます。

今回、自社の便利ツール集「シルギア」に法定相続分・遺留分の計算ツールを1本追加しました。着手(リポジトリ把握)から本番公開まで12分56秒。ただし本題は速さではありません。この開発では、先に書いたテストが、民法の解釈誤りを1件、公開前に捕まえました。テストが無ければ、法律的に誤った数字を載せたまま公開していた——その一件をどう作り、どう捕まえたかを、エンジニア向けにまとめます。決済者・非エンジニア向けの要約版は 実績ページの事例(相続の取り分がわかるツール) にあります。実物は こちら(公開中) で触れます。

先に断っておくと、12分56秒はゼロからの構築ではありません。共有デザイン・デプロイスクリプト・構造化データ生成器がすでにある monorepo に、ツールを1本足した時間です。土台が無ければこの速さは出ません。速さの話は後半に少しだけ書きます。

なぜ「相続の計算」を選んだか ― 条文の分岐がそのまま仕様になる

単位変換や日付計算のような題材は、テンプレートの流用で作れてしまい、AI駆動開発の検証になりません。あえて選んだのは、民法の条文がそのまま分岐になる相続計算です。相続人が誰か(配偶者・子・直系尊属・兄弟姉妹)で取り分が変わり、そこに代襲相続(孫・甥姪)、半血の兄弟姉妹、そして遺留分が重なります。

この手の題材は、仕様書を書くこと自体が難しい。だからこそ「条文=テスト」の形に落とせるかが勝負になります。実装が正しいかどうかは、最終的に「その条文どおりの数字が出るか」でしか判定できないからです。

相続の取り分がわかるツールの画面。家族構成を選ぶと法定相続分と遺留分が分数と割合で表示される
家族構成を選ぶと、法定相続分と遺留分が分数と割合で表示されます。分数表示なのは、内部で有理数のまま計算しているためです。

設計で先に決めた2点

実装をAIに任せる前に、人(=レビュー担当)が決めたのは、次の2点だけです。これはAIへの指示というより、「AIに任せる範囲を、後から検証できる形に切る」ための境界設定でした。

  • 計算ロジックをUIから完全に切り離す。純粋関数として calc.js に置き、DOM もブラウザも介さずに呼べるようにする。これでテストは Node 標準の node --test だけで回り、UIの都合とロジックの正しさが混ざらない。
  • 条文ごとにテストを書く。民法 900条1〜4号 / 887条2項 / 889条 / 890条 / 1042条を、それぞれ最低1件のテストで固定する。テストが仕様書を兼ねる。

この2点が、後で効いてきます。ロジックがUIから独立していなければ「配偶者と兄弟姉妹のケースの遺留分」だけを単体で叩けませんし、条文ごとにテストが無ければ、どの条文の解釈が間違っているのかを名指しできません。

丸め誤差を持ち込まない ― 有理数のまま計算する

相続の取り分は 1/2、1/3、2/3、1/6 といった分数の世界です。ここを浮動小数点で扱うと、1/3 が 0.3333… になり、按分の合計が 1 にならなかったり、表示のために丸めた瞬間に「合計 99.9%」のような数字が出ます。法律の計算でこれは許されません。

そこで、割合は最後まで約分つきの有理数(分子・分母のペア)として持ち、小数化するのは表示の直前だけにしました。加減乗除と約分を持つ小さな有理数ユーティリティがあれば十分で、外部パッケージは要りません。結果として、1/3 のような値でも丸め誤差ゼロで按分でき、分数表示もそのまま出せます。

テストを「仕様書」として先に置く

条文ごとにテストを書く、というのは具体的にはこういうことです。相続人の組み合わせごとに、期待する分数を条文とセットで固定します。下は概念を示すためのイメージで、実際のテストは計算ロジックの単体テストとして 21件あります(すべて計算ロジックのテストで、UIの自動テストは含みません)。

// イメージ(概念)。条文と期待値をセットで固定する。
// 民法900条1号:配偶者と子 → 配偶者 1/2、子で 1/2 を等分
test('900条1号 配偶者+子2人', () => {
  const r = legalShares({ spouse: true, children: 2 });
  assert.deepEqual(r.spouse, frac(1, 2));
  assert.deepEqual(r.children, [frac(1, 4), frac(1, 4)]);
});

// 民法1042条:遺留分。ここに落とし穴があった(後述)
test('1042条 配偶者+兄弟姉妹の遺留分', () => {
  const r = legalReserve({ spouse: true, siblings: 2 });
  assert.deepEqual(r.spouse, frac(1, 2)); // ← 3/8 ではない
});

ポイントは、テストの期待値を人が条文から決めていることです。実装をAIが書き、期待値を人が条文で確定する。この非対称性が、次の一件を捕まえました。

テストが法律の誤りを1件、公開前に捕まえた

ここがこの事例の本題です。最初の実装は、遺留分を「総体的遺留分 × その人の法定相続分」で一律に計算していました。式としては自然で、コードを読んでも違和感がありません。ところが、配偶者と兄弟姉妹が相続人になるケースで、テストが赤くなりました。実装は配偶者の遺留分を 3/8 と出したのです。

正しくは 1/2 です。理由は民法1042条にあります。兄弟姉妹は遺留分権利者ではないため、遺留分の按分の母数に兄弟姉妹を入れてはいけません。ところが「総体的遺留分 × 法定相続分」という素直な式は、兄弟姉妹の法定相続分ぶんを母数に含めてしまい、その結果、配偶者の取り分が本来より小さく(1/2 → 3/8 に)出てしまっていた、というわけです。

配偶者+兄弟姉妹のケース最初の実装正しい値(1042条)
配偶者の遺留分3/8(誤り)1/2
兄弟姉妹の遺留分按分に参加なし(遺留分権利者でない)
「総体的遺留分 × 法定相続分」という自然な式が、遺留分権利者でない兄弟姉妹を母数に入れてしまう。テストの期待値(1/2)が実装(3/8)と食い違って発覚しました。

強調したいのは、この誤りは「バグ」ではなく「法解釈の誤り」だったことです。プログラムとしてはエラーも例外も出ません。数字もそれらしく出ます。レビューでコードを目で追っても、遺留分の条文を頭に入れていなければ見逃します。AIが書いたコードで、こういう「動くが間違っている」が最も危ない。これを止められるのは、コードの見た目ではなく、条文から決めた期待値だけです。

速く作れることより、速く作っても間違いに気づける仕組みがあることのほうが価値がある。

もしテストを後回しにして「動いたから公開」していたら、配偶者の遺留分が 3/8 という法律的に誤った数字を、相続を調べに来た人に見せていました。テストを先に置いたことの価値は、速度ではなく、この1件に凝縮されています。

計測(実測値・母数と条件つき)

数字はすべて実測です。誇大にならないよう、条件を添えます。

項目実測値条件
リポジトリ把握から本番公開まで12分56秒既存 monorepo に1本追加した時間。ゼロからの構築ではない
テスト21件すべて通過計算ロジックのテスト。UIの自動テストは無い
追加した転送量37.7KB共有アセットを除く(HTML 19.4 / calc.js 8.3 / app.js 8.1 / CSS 1.9)
TTFB(応答開始まで)0.08〜0.11秒共有アセットを除く本番URLへの curl 実測
外部パッケージ0フレームワーク・バンドラ・npm依存なし
JSエラー0ヘッドレスChromeのコンソール(macOS固有の描画ログは除外)
12分56秒は既存の仕組みに1本足した時間です。テストは計算ロジックのみで、UIの自動テストは含みません。転送量・TTFBは共有CSS/JSを除いた実測です。

配信はエックスサーバー共有ホスティング上の静的ファイル(PHPを通さない)です。PWA(manifest + service worker)でオフラインでも動きます。構造化データ(WebApplication / BreadcrumbList / FAQPage / HowTo)は tool.json から生成器で吐き出しています。

「土台があるから速い」の中身

12分56秒という数字だけを見て「AIなら何でも速い」と受け取られると困るので、内訳の考え方を書いておきます。この速さは、作るもの(相続ツール)より前に、作り続けられる土台が用意されていたから出たものです。具体的には、共有デザイン、ワンコマンドのデプロイスクリプト、構造化データの自動生成器。新しいツールは「その土台に1本差し込む」だけなので、AIはツール固有のロジックとテストに集中でき、周辺の定型作業をほぼ踏まずに済みました。

逆に言えば、同じ速さを別プロジェクトで再現したいなら、まず土台を整えるのが先です。AI駆動開発の速さは、モデルの性能というより「AIが1本に集中できるよう、周辺をどれだけ定型化してあるか」で決まる、というのがこの事例の実感でした。

正直に、測っていないこと

  • Lighthouse スコア … PageSpeed Insights API が日次クォータ超過で取得できず、実測していません。書きません。
  • AI利用コスト(いくらで作れたか) … セッションのコストを計測する手段が手元に無く、実測できていません。「いくらで作れた」は書けません。
  • 従来の目安見積との比較 … 人手のみで同等物を作る場合の社内基準値が未設定です。基準が無い比較は書きません。
  • 公開後の不具合件数 … 公開直後のため未計測です。

他の案件にも持っていける設計

  • ロジックをUIから切り離してテストする。法令・料金表・業務ルールのように「条件分岐が仕様そのもの」の案件では、この分け方がそのまま効きます。AIに任せる範囲を、そのまま検証できる単位に切る、ということです。
  • 条文・規程の単位でテストを書く。テストが仕様書を兼ね、レビューのときに「どの条文を満たしているか」が読み取れます。落ちたテストが、どの解釈が誤りかを名指ししてくれます。
  • 割合は有理数で扱う。按分・分配を丸め誤差なしで扱え、分数のまま表示もできます。
  • 期待値は人が、実装はAIが。AIは「動くが間違っている」コードを書きます。それを止めるのは、人が根拠(条文・規程・料金表)から確定した期待値です。この非対称性を設計に組み込むのが肝でした。

まとめ

AI駆動開発の価値は、速さそのものではありません。速く作っても、公開前に間違いへ気づける仕組みを一緒に持てるかです。今回はテストを先に置いたことで、民法の解釈誤り(配偶者の遺留分 3/8 → 正 1/2)を1件、公開前に捕まえられました。「条件分岐がそのまま仕様になる」システムほど、この進め方の効きが大きくなります。

実物は 相続の取り分がわかるツール(シルギア) で公開中です。決済者・非エンジニア向けの要約は 実績ページの事例 に、AI活用の他の事例は AI活用ページ にまとめています。料金表・業務規程・法令のように「条件分岐がそのまま仕様になる」システムのご相談は お問い合わせ から。

B!
← 一覧へ戻る