# 開発進捗ログ

<!--
本ファイルは追記型のフル進捗ログ．

- 最新エントリは下に追記する（時系列順．古いものが上，新しいものが下）
- CLAUDE.md の「開発進捗」セクションは最新 1 行のみ（上書き運用）
- 詳細・失敗パターン・設計判断はすべて本ファイルに残す
- 書式・運用ルールは .claude/rules/progress-log.md を参照
  （本ファイルの編集時に自動ロードされる）
-->

- [x] **/setup フェーズ 1〜2 完了（要件定義・技術選定）**: 旧実装 `org/src`（C++ / MFC / OpenCV 2.4）を解析し，同一機能の再構築を目的として PLAN_01・ENV_01 を作成．開発モードは solo．
  - 設計判断: 技術スタックは Python + PySide6 + opencv-python を採用．MFC 継続・C# 案は Mac 対応の可能性が無いため却下（ユーザー要件: 当面 Windows，将来 Mac も視野）．SVM は現行と同じ OpenCV 実装（`cv2.ml.SVM`）を使い診断結果の同一性を担保する方針
  - 旧実装は `org/` に置き参照専用とする（.gitignore で Git 管理外）
- [x] **/setup フェーズ 3 完了（環境構築）**: ENV_02（メンバー用）・ENV_03（管理者用）を作成．「どのデバイスでも clone → uv sync で開発再開できる」を方針とし，環境定義は pyproject.toml / uv.lock でリポジトリ内に持たせる（デバイス側は git / gh / uv のみ）．ENV_04（開発コマンド）は pyproject 作成時に確定させるため後回し．GitHub リポジトリ作成はユーザー実施待ち（ENV_03 参照）
- [x] **/setup フェーズ 4 完了（仕様設計）**: 旧実装の解析から SPEC_01（画面仕様）・SPEC_02（診断ロジック仕様）を作成．
  - 設計判断: ① 診断失敗検出は現行のマジックナンバー比較（スコア 42/0/5/11/3 一致）をやめ原因の直接検出に変更 / ② 日本語結果画面は文字入りビットマップ背景をやめ描画生成に変更（アセット非依存・表示は現行踏襲）/ ③ Lab 変換は CIE 標準の低輝度分岐を持たない現行式を意図的に踏襲（結果同一性優先）
- [x] **/setup フェーズ 5 完了（規約整備）**: Python スタック向け path-scoped rules（coding-style / project-structure / testing / error-handling）を作成．パッケージ名は `tiasjudge`（src レイアウト，core と gui を分離），テストは旧実装との回帰テストを最重視，GUI 自動テストは書かない方針
- [x] **/setup フェーズ 6 完了（開発計画）**: PLAN_02 を作成．core 先行の 8 ステップ構成（骨格 → csv_io → color → svm → 回帰テスト → GUI 2 画面 → 配布）．M1 = 旧実装との結果一致の証明（ステップ 5，旧 exe での入出力採取にユーザー協力が必要），M2 = アプリ置き換え可能
- [x] **/setup フェーズ 7 完了（立ち上げ完了）**: CLAUDE.md を最終更新（概要にスタック明記・必須ルール・ドキュメント一覧）．プロジェクト立ち上げフローはすべて完了．次は PLAN_02 ステップ 1（プロジェクト骨格）を `/implement` で開始する
- [x] **PLAN_02 ステップ 1 完了（プロジェクト骨格）**: pyproject.toml（uv + hatchling，src レイアウト）・`src/tiasjudge/{core,gui}` 骨格・`data/data.csv`（CP932→UTF-8 変換配置）・ENV_04（開発コマンド）を作成．`uv sync` → `uv run pytest` 通過を確認
  - 設計判断: opencv-python は無指定だと 5.0.x が入るため，ENV_01 の「OpenCV 4.x」と `cv2.ml.SVM` の挙動同一性を優先して `>=4.10,<5` に固定
  - 発見: `data.csv` の実体は 198 列（医師 39 ブロック）だが末尾ブロックは全 0 の未使用列で，有効データは SPEC_02 どおり 38 名分＝193 列（SPEC_02 に注記済み）．旧実装の読込列数はステップ 2 で `org/src` と突き合わせて確定する
  - 未実装・後段: `__main__.py` はプレースホルダ（ステップ 6 で GUI 起動に差し替え）．pytest-cov はステップ 2 以降で導入検討
- [x] **PLAN_02 ステップ 2 完了（core: CSV 読込）**: `core/csv_io.py`（変換行列 17×3・data.csv の読込と形式検証，専用例外 3 種）を実装（無人運転）
  - 確定事項: 旧実装の data.csv 読込は **193 列**（`EXP_OUTPUT_DIM=190`＝38 名 × 5 色，`CsvRead` cols=193）．実ファイル末尾 5 列は旧実装でも未読．SPEC_02 の注記を確定版に更新済み
  - 設計判断: dtype は旧実装（`CV_32F`・int キャスト）に合わせ lab=float32 / evaluations=int32．変換行列は計算精度優先で float64（旧実装も double で計算）
  - レビューポイント（仕様に規定なし・挙動は現状維持のまま起床後の判断待ち）: ① 変換行列の nan/inf セルを受理する（有限値チェック追加の要否）/ ② 評価列 `1.0` 表記を 1 と解釈する / ③ UTF-8 失敗時の cp932 フォールバックの要否（ENV_01 の UTF-8 統一方針との整合）/ ④ 変換行列は 17 行ちょうどを要求（旧実装は 18 行以上でも先頭 17 行で通す）
  - 旧実装の潜在バグ発見: `Readfile()` の係数初期化ループが `i < 16` までで `a[16]` 等が未初期化（正常な 17 行ファイルなら影響なし．新実装には持ち込まない）
- [x] **PLAN_02 ステップ 3 完了（core: 色変換）**: `core/color.py`（RGB→XYZ 17 項多項式・XYZ→Lab 現行式）を実装（無人運転）．C++ 逐語移植の参照実装と 4 ケースでビット一致を確認
  - 設計判断: 旧実装の精度を忠実に再現（係数 float32 保持 → double 演算 → Lab を float32 丸め）．SPEC_02 に精度踏襲の注記を追加．CIE 低輝度分岐は仕様どおり実装しない（テストは「分岐が入っていないこと」まで検証済み）
  - テストの検出力をミューテーション 6 種（項順入替・クリップ削除・CIE 分岐追加等）で確認し全検出
  - 留意（ステップ 4 へ）: XYZ=0 のとき L\*=−16 と負値になり学習データの範囲（0〜100）外の入力が SVM に入りうる（旧実装と同一挙動．問題ではないが把握しておく）
- [x] **PLAN_02 ステップ 4 完了（core: SVM 分類・ROI）**: `core/svm.py`（190 列 SVM 学習・予測・5 色スコア・上位 2 色・失敗検出）と `core/roi.py`（51×51 ROI 平均色）を実装（無人運転）
  - 確定事項: 旧実装の SVM パラメータは C_SVC / RBF / γ=0.011 / C=12.0 / termCrit=EPS のみ（OpenCV 2.4 と 4.x で termCrit の解釈が同一であることをソース比較で確認．COUNT を足すと挙動が変わるため足さない）．旧失敗判定マジックナンバー（42/0/5/11/3）は「域外入力に対する SVM の既定応答」であることを実測で特定し，Lab=(−16,0,0) で新実装から完全再現（旧実装との挙動一致の強い傍証）
  - **⚠ 要レビュー（無人運転中の仕様変更判断）**: 失敗検出を「直接検出のみ」とする /setup 時の設計判断を一部戻した．直接検出だけでは L\* が小さい正値の域外入力（旧実装は失敗表示）を取りこぼし「紫 42%」等の誤結果を表示してしまうことが tester の実測で判明したため，最上位ルール「診断結果は旧実装と一致」を優先し，**旧パターン判定（42/0/5/11/3 → OUT_OF_DOMAIN）を直接検出と併用する形で復活**させた．SPEC_02「診断失敗の判定」節を改訂済み．異議があれば `LEGACY_FAILURE_PERCENTAGES`（svm.py）と当該節を戻すこと
  - 設計判断: 集計の単精度丸め（float32 逐次加算・float32 100 倍 → 偶数丸め）と上位 2 色タイブレーク（旧 std::map キー順 crimson→dark_red→pink→purple→pale）まで旧実装を再現．ROI 範囲外は旧実装のクラッシュを ValueError に置換（GUI 側でガード前提）
  - 未実装・後段: TRAINING_FAILED / PREDICTION_FAILED は健全な入力から再現不能のためテスト未発火．GUI 実装時に 5 点目クリックのガードが必要（MAX_ROI_POINTS は core 側の定数のみ）
