• #case100
  • #Excel
  • #TypeScript
  • #Python
  • #パイプライン
  • #簿記
開発eurekapu-nuxt4

朝6時51分、Claude Codeに最初の指示を投げ込んだ。「ある会計の参考書、100ケース分の仕訳をExcelで一元管理して、そこからTypeScript静的データを吐き出すパイプラインを作る」。昼前には79論点まで自動生成できる仕組みが立ち上がり、verify_xlsxBS check=0PL↔BS整合通過 と返した。途中、PowerShellのUTF-8 BOMが日本語を文字化けさせ、run.ps1$root が1階層浅く動かず、Codexのサンドボックスが入力ファイルを読まずに落ちた。Codexレビュー(GPT-5.5)を3ラウンド回して計画書から致命指摘を5件潰し、引き継ぎメモも別ラウンドで「初見でわかるか」を別のCodexに点検させた。4論点→18論点→55論点→79論点と段階的に拡張するたびに verify を通し、最後は基本ケース9件のうち2件(ID 1007/1008)と通常ケース ID 48〜63 を加えた構成に着地した。

朝: 書籍構成を3層に整理してID体系を決める

参考書の構成を眺めた。基本ケース9件、通常ケース100件、コラム6件。3層に分かれている。Web側でURLや配列キーに直結させたいので、書籍番号と整数IDを直結させたい。

ID体系をこう決めた。

  • 基本ケース: 1001〜1009(9件)
  • 通常ケース: 1〜100(書籍番号と一致)
  • コラム: 2001〜2006(6件)

書籍番号と直結させた瞬間、「この論点はケース48です」とユーザーが指せば、Excel・TypeScript・Vueページのどこを触ればいいかが3秒で分かるようになった。

共通期首仕訳は論点ごとに複製する

最初に悩んだのは「設立出資」「機械装置取得」など、複数論点で共通する期首仕訳をどう扱うか。普通ならマスタテーブルに切り出して論点側からFKで参照したくなる。

だが今回は逆に振り切った。共通仕訳でも論点ごとに複製する

理由はひとつ。集計を単純にしたい。論点ごとに「この論点で発生した全仕訳」を1テーブルから引けば期首BSも当期PLも全部計算できる。マスタを参照して再構築するロジックは書きたくない。

正規化を捨てた瞬間、verify_xlsx の集計コードが10行で書けた。

純資産は感情科目レベルで増減内容を持たせる

純資産科目は、ただの「資本金」ではなくて、資本金_新株発行 資本金_設立出資 のようにアンダースコア区切りで増減内容を後ろに付ける形にした。

# 純資産科目の命名規則
"資本金_設立出資"     # 設立時の出資による増加
"資本金_新株発行"     # 新株発行による増加
"利益剰余金_当期純利益" # PLからの振替

CFで見せるときに「資本金が動いた理由」を1行で表示できるし、PL→BSの振替も 利益剰余金_当期純利益 でラベルが立つ。BS残高表示時は _ で区切って前半だけ集計すれば普通の純資産表示に戻る。

Excel側はPython、TypeScript側はtsxで生成

パイプラインを2段に切った。

  1. Python (xlsx_helpers): Excel仕訳DBを生成・検証
  2. TypeScript (tsx): ExcelからVue.js用静的データ(cases.ts)を生成

Pythonでやる理由は openpyxl の安定性と、検証ロジックを書きやすい点。TypeScriptでやる理由は出力先がVueのコンポーネントなので型を揃えたい点。

# パイプラインの叩き方
python xlsx_helpers/generate.py --cases 1,2,3,...,79
python xlsx_helpers/verify.py    # BS check=0 / PL↔BS 整合
npx tsx scripts/xlsx-to-ts.ts    # cases.ts を生成

段階拡張: 4→18→55→79論点

一気に79論点を生成しようとすると失敗時の切り分けがしにくい。段階的に拡張した。

  • 4論点: パイプラインの骨格確認。Excel生成→verify→TypeScript出力まで通すだけ
  • 18論点: 基本ケース9件+通常ケースの最初の数件。BS整合のテストパターンを増やす
  • 55論点: 通常ケースを大幅追加。設立出資・機械装置取得の複製パターンが現実的になる
  • 79論点: 最終的な目標。ID 48〜63 を加えてカバレッジを伸ばす

各段階で verify_xlsx を通した。BS check=0PL↔BS整合通過 の両方が出るまで次に進まない。

試行錯誤: PowerShell UTF-8 BOM で日本語が崩れた

最初に書いた run.ps1Set-Content -Encoding UTF8 を使っていたら、出力された cases.ts の先頭に BOM が入って、tsx が読み込んだ瞬間に日本語が ��� に化けた。

PowerShell の -Encoding UTF8 は BOM 付きのUTF-8を意味する。BOMなしを使いたい場合は [System.IO.File]::WriteAllText を使うか、tsx 側で書き出すしかない。

切り替えた。tsx 側で fs.writeFileSync(path, content, 'utf-8') に統一。BOMなしの素のUTF-8で出力されて、Vue側のインポートも問題なく通った。

試行錯誤: run.ps1$root が1階層浅かった

run.ps1 の冒頭で $root = Split-Path $PSScriptRoot -Parent と書いていたら、想定より1階層浅いディレクトリを $root として認識していた。スクリプトの設置場所を xlsx_helpers/scripts/ に移したのに Parent が1回ぶん足りなかった。

# Before
$root = Split-Path $PSScriptRoot -Parent

# After
$root = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent

修正後、xlsx_helpers/cases/*.xlsx が正しく見つかるようになった。

試行錯誤: Excel が文字化け

途中で生成した Excel をブラウザで開いたら、シート名が文字化けしていた。Python 側で openpyxl のシート作成時に内部エンコーディングを CP932 と勘違いして書き出していたのが原因。明示的に UTF-8 を指定して書き直したら直った。

書き直し後の Excel を再読込してverifyを通した。BS check=0、PL↔BS整合通過。

試行錯誤: Codex のサンドボックスエラー

計画書のレビューを Codex GPT-5.5 に投げたら、サンドボックスが入力ファイルを読み込めずに落ちた。

codex exec -m gpt-5.5 "..."
# Error: cannot read file in sandbox

Codex CLI のサンドボックスは外部ファイルへのアクセスを制限している。--bypass 系のフラグを付けて再試行したら通った。

codex exec --dangerously-bypass-approvals-and-sandbox -m gpt-5.5 "..."

Codex レビュー: 3ラウンドで5件の致命指摘を反映

計画書(memo/2026-05-03/case100-pipeline-plan.md)を Codex GPT-5.5 にレビューさせた。3ラウンド回した。

  • Round 1: ID体系の衝突可能性、純資産科目の命名一貫性、verify ロジックの境界条件
  • Round 2: from2 の前年度集計が論点をまたぐ場合の挙動、PL会計年度の境界
  • Round 3: 引き継ぎメモが「初見でわかるか」を別のCodexに点検させる

致命指摘5件を計画書に反映してから着手した。瑣末な点へのクソリプは無視し、根本的な設計上の穴だけ拾った。

from2 で前年度まで集計すれば BS は引き継げる

期首BSをどう作るかで悩んだ。論点ごとに preposted を全部書くのは冗長すぎる。

from2 カラムを足した。各仕訳に「会計年度2 から有効」のフラグを立てる。期首BSは「from2 より前の年度の仕訳をすべて集計した結果」として動的に計算する。

// 期首BS計算
const openingBS = journals
  .filter(j => j.fiscalYear < currentFY)
  .reduce(accumulateBalance, {})

PLは会計年度のフラグだけでフローを拾えばいい。BSは累積、PLはフロー、という会計の基本構造をそのままコードに落とした瞬間、verify が通った。

学び

正規化を捨てると集計が10行で書ける。 共通仕訳をマスタに切り出してFKで引っ張ると見た目はキレイだが、検証コードが分岐だらけになる。論点ごとに複製した瞬間、「この論点の全仕訳を1テーブルから引く」だけで済むようになって、verify_xlsx が10行で書き上がった。

段階拡張すると失敗の切り分けがしやすい。 一気に79論点を生成して落ちると、どの論点が原因か見つけるのに30分かかる。4→18→55→79と4段階に分けたら、各段階で30秒で原因論点を特定できた。

PowerShellの -Encoding UTF8 はBOM付き。 Windows特有の罠。tsx側で fs.writeFileSync(path, content, 'utf-8') に統一した瞬間、文字化けが消えた。Windows で Web向けデータを書く時は PowerShell の Set-Content を避ける。

Codex レビューは3ラウンド回して致命点だけ拾う。 1ラウンドだと表面的な指摘しか出ない。3ラウンド目で「初見でわかるか」を別のCodexに点検させると、引き継ぎメモの抜けが浮き彫りになった。

from2 で前年度集計すればBSは引き継げる。 期首BSを preposted で全部書く必要はない。各仕訳に from2 フラグを立てて、当期より前の年度を全部集計すればBS残高は自動的に再現される。会計の基本構造(BSは累積、PLはフロー)をコードに落としただけだが、書き上がるまで気づかなかった。

明日やること

  • 残り21論点(80〜100)をパイプラインに流して通常ケースを完成させる
  • コラム6件(ID 2001〜2006)の構造をパイプラインに組み込む
  • cases.ts をVue側で読み込んで、79論点のインタラクティブHTMLを生成するエージェントを並列起動する
  • xlsx_helpers/verify.py の出力に「どの論点でBS不整合が出たか」をJSON形式で吐き出す機能を追加して、生成失敗時の切り分けを30秒→3秒に短縮する
  • 引き継ぎメモを memo/2026-05-03/case100-pipeline-handover.md に固定し、明日朝のリマインドに添付する