run.py:549-595で無効化しているのは住所/地価オーバーライド変更だけです。run.py:598-613は*_output.csvが存在するだけで企業をスキップします。run.py:1079-1084は一時ファイルを使わず最終出力先を直接wで開くため、途中終了すると 0 byte CSV が残ります。- 実データにも
data/output/6501_output.csv,7425_output.csv,7575_output.csv,7596_output.csv,7615_output.csv,7619_output.csv,7980_output.csvの 7 件の空ファイルが残っています。
この設計では、空ファイルも次回以降ずっと処理済み扱いになります。さらに、XBRL 原本、時価総額、地価 GeoJSON、ジオコード参照データ、CLI パラメータが変わっても既存 CSV は再計算されません。結果が静かに陳腐化するため、ランキング用途では高リスクです。
rust_src/landprice_tokyo.rs:78-126でL01_001/L01_002/L01_003からpoint_idを作り、point_idx_by_id.insert(...)しています。rust_src/landprice_tokyo.rs:196-207はその ID から用途区分を引き直します。run.py:912-927はこの用途区分をlanduse_matchの基準用途や表示値に使っています。
現在の data/landprice/merged/L01_L02_merged_13.geojson には同一 point_id が 1,053 件あり、そのうち 435 件は用途区分が衝突しています。実例として 13101-000-002 は 2 点あり、座標 139.73752,35.6812 の最近傍は単価 2,530,000 円の 2住居 ですが、get_point_landuse_kind("13101-000-002") は後勝ちで 1住居 を返します。
つまり、最近傍点そのものは正しく選ばれていても、その後の用途区分参照だけ別地点の値になります。landuse_match の再検索対象、出力 CSV の 最近傍用途区分、監査時の公示点 ID が信用できなくなります。
src/utils.py:19-33はcontextmanagerの中でyield後にUnicodeDecodeErrorを捕まえ、次の encoding で再度yieldしようとしています。
CP932 ファイルを読むと、最初の utf-8-sig 読み込み中に例外が発生したあと RuntimeError: generator didn't stop after throw() になります。open_csv() の docstring は CP932 対応をうたっていますが、実装上その経路は使えません。入力 CSV やランキング集計元 CSV を CP932 で渡すと失敗します。
run.py:520-527のgeocode_deps_hashはGAIKU_CSVとGEOCODE_RSだけを使っています。- しかし
rust_src/geocode_tokyo.rs:63-115ではOAZA_CSVからoaza_firstとmuni_centroidを構築しています。
そのため町丁目参照データだけを差し替えた場合、既存の oaza_chome / muni_centroid キャッシュは削除されません。低解像度住所の位置だけが古い値のまま残るため、参照データ更新後の再計算結果が混在します。
scripts/merge_address_patches.py:87-129は、パッチ内の企業値が辞書でない場合に警告してスキップしますが、そのファイルをmerged_patch_filesに追加して最後に削除します。
再現例では "'1234': broken" のような不正パッチを渡すと、警告を出したうえで merged_count=1、元ファイル削除、overrides.yaml は空のままになります。自動調査で生成された手動補正データを、異常時に静かに失う経路です。
src/ranking_data.py:138-143はリンク URL を HTML エスケープするだけで scheme を制限していません。src/web.py:65-82はその HTML を Web UI に渡します。
[x](javascript:alert(1)) は <a href="javascript:..."> として出力されます。メモはリポジトリ内ファイルですが、並列調査エージェントの生成物をそのまま公開 UI へ載せる設計なので、少なくとも http/https 以外を拒否する防御は必要です。
skip_processedは「途中再開の高速化」目的と理解しましたが、現状は成果物の妥当性検証や生成条件の署名がありません。意図が完全再計算回避なら、出力単位で依存ハッシュを持つ設計が必要です。- 地価点 ID は公開データ由来の正式識別子ではなく、少なくともこのリポジトリ内では一意でない前提で扱う必要があります。
data/cache/と既存data/output/はレビュー対象外の派生成果物としましたが、空 CSV はコード不具合の現物証拠として確認しました。
uv run pytest-> 187 passedcargo test-> 38 passednpx tsc --noEmit-> successuv run ruff check .は NixOS の動的リンク制約で起動できず未実施
- 空 CSV / 不完全 CSV を
skip_processedが再処理することを確認するテストがありません。 - 実データのような重複
point_idを含む地価 GeoJSON の回帰テストがありません。 - CP932 入力を
open_csv()で読むテストがありません。 OAZA_CSV変更時にジオコードキャッシュを失効させるテストがありません。- 不正なパッチファイルを保持するテストがありません。
- 調査メモの URL scheme 制限に関するテストがありません。