diff --git a/.claude/rules/coding-style.md b/.claude/rules/coding-style.md new file mode 100644 index 0000000..f3e1fc7 --- /dev/null +++ b/.claude/rules/coding-style.md @@ -0,0 +1,41 @@ +--- +paths: ["src/**", "tests/**"] +--- + +# コーディング規約 (Coding Style) + +Python コードを書くときは本規約に従うこと.基本方針として [PEP 8](https://peps.python.org/pep-0008/) と Ruff のデフォルトルールに準拠し,プロジェクト固有の上書き項目のみ以下に定める. + +## フォーマット・lint (Format & Lint) + +- フォーマット・lint は **Ruff** に一任する(`uv run ruff format` / `uv run ruff check`).手動整形で Ruff と争わない +- 1 行の長さ: 100 文字(pyproject.toml の `line-length` で設定) +- 文字コード: UTF-8.ソース内の日本語(コメント・UI 文字列)は UTF-8 で直接書く + +## 命名 (Naming) + +- モジュール・関数・変数: `snake_case`/クラス: `PascalCase`/定数: `UPPER_SNAKE_CASE`(PEP 8 どおり) +- 旧実装のハンガリアン記法(`m_Img`・`m_xView` 等)は**移植時に廃止**し,意味の分かる名前に付け替える +- 診断ドメインの用語は英語に統一する(例: `tongue_color`,`transform_matrix`,`diagnosis_result`).5 色のキーは `purple` / `dark_red` / `crimson` / `pink` / `pale` を使う + +## 型ヒント (Type Hints) + +- 関数・メソッドの引数と戻り値には型ヒントを必ず付ける +- NumPy 配列は `numpy.typing.NDArray` を使い,dtype が重要な箇所は docstring で形状・dtype を補足する + +## コメント・docstring (Comments & Docstrings) + +- docstring・コメントは日本語でよい +- 公開関数(core パッケージの API)には docstring を付け,1 行要約+必要なら引数・戻り値の説明を書く +- 旧実装との対応が保守に役立つ箇所(数式・パラメータ等)は「現行実装踏襲」の旨と根拠(SPEC_02 参照等)をコメントで残す + +## import (Imports) + +- 並び順は Ruff(isort ルール)に一任する +- `from module import *` は禁止(旧実装の `using namespace cv` に相当する濫用を避ける) +- OpenCV は `import cv2`,NumPy は `import numpy as np` の慣用名を使う + +## その他 (Miscellaneous) + +- パス操作は `pathlib.Path` を使う(`os.path`・文字列連結は使わない).**絶対パスのハードコード禁止**(ENV_02「環境再現性のルール」参照) +- マジックナンバーは定数化する(ROI サイズ・SVM パラメータ・白色点等は SPEC_02 と対応する名前を付ける) diff --git a/.claude/rules/error-handling.md b/.claude/rules/error-handling.md new file mode 100644 index 0000000..88bdcad --- /dev/null +++ b/.claude/rules/error-handling.md @@ -0,0 +1,29 @@ +--- +paths: ["src/**"] +--- + +# エラーハンドリング方針 (Error Handling Policy) + +エラー処理・ログ出力を書くときは本方針に従うこと. + +## エラーの分類と処理 (Classification) + +| 分類 | 例 | 処理 | +| --- | --- | --- | +| ユーザー入力エラー | 拡張子違い,クリック数超過,未読込での診断 | `gui/` でガードし,メッセージボックスで案内(文言は SPEC_01「入力ガード」) | +| データエラー | 変換行列 CSV の形式不正,data.csv の欠損 | `core/` が専用例外を送出し,`gui/` が捕捉してエラーダイアログ表示 | +| 診断失敗 | SVM が学習不能(正例不足等) | `core/` が失敗を示す結果を返し,結果画面に「Diagnosis failed」を表示(SPEC_02「診断失敗の判定」) | +| バグ(想定外) | 上記以外の例外 | 捕捉して握りつぶさない.スタックトレースをログに残して落とす | + +## 規則 (Rules) + +- `core/` に専用例外を定義する(例: `DataFormatError`).`core/` は **GUI を知らない**ため,メッセージボックス表示等は行わない(依存方向は project-structure.md 参照) +- 例外の握りつぶし(`except Exception: pass`)は禁止.捕捉するのは「その場で意味のある対処ができる」場合のみ +- 入力値の検証は境界(ファイル読込直後・GUI 入力時)で行い,`core/` の内部では検証済みを前提とする +- 旧実装の「エラーをマジックナンバーで表現する」方式(診断失敗 = 特定スコア組)は移植しない.失敗は例外または明示的な結果型で表す + +## ログ (Logging) + +- 標準ライブラリの `logging` を使う.`print` によるデバッグ出力を残さない +- `core/` はモジュールロガー(`logging.getLogger(__name__)`)を使い,出力先の設定はエントリポイント側で行う +- 診断実行時は入力(Lab 値)と出力(5 色スコア)を INFO で記録する(研究用途での再確認・回帰テストデータの収集に使うため) diff --git a/.claude/rules/project-structure.md b/.claude/rules/project-structure.md new file mode 100644 index 0000000..3fca24f --- /dev/null +++ b/.claude/rules/project-structure.md @@ -0,0 +1,40 @@ +--- +paths: ["src/**", "tests/**", "data/**", "pyproject.toml"] +--- + +# プロジェクト構成 (Project Structure) + +ファイルを新規作成・移動するときは本構成に従うこと. + +## ディレクトリ構成 (Directory Layout) + +```text +TIASjudge/ +├── src/ +│ └── tiasjudge/ +│ ├── core/ # 診断ロジック(UI 非依存) +│ │ ├── color.py # RGB→XYZ→Lab 変換(SPEC_02 (1)(2)) +│ │ ├── svm.py # SVM 学習・5 色分類(SPEC_02 (3)) +│ │ ├── roi.py # ROI 平均色の算出(SPEC_02 (0)) +│ │ └── csv_io.py # 変換行列・data.csv の読込 +│ ├── gui/ # PySide6 画面(SPEC_01) +│ │ ├── main_window.py +│ │ └── result_window.py +│ └── __main__.py # エントリポイント(python -m tiasjudge) +├── tests/ # pytest(src/ と同じ構造をミラーする) +├── data/ # 学習データ等の同梱ファイル(data.csv) +├── docs/ # ドキュメント(docs-naming.md 参照) +└── org/ # 旧実装(Git 管理外・参照専用) +``` + +## 依存方向のルール (Dependency Rules) + +- `core/` は **PySide6・GUI に依存してはならない**(import 禁止).純粋な計算・入出力のみ +- `gui/` は表示とイベント処理に徹し,診断計算を実装しない(必ず `core/` を呼ぶ) +- `core/` はファイルパスを引数で受け取る.モジュール内でパスを固定しない(テスト容易性と再現性のため) + +## 配置ルール (Placement Rules) + +- 新しいロジックは まず `core/` に置けないか検討する(UI 非依存にできるものは core へ) +- テストは `tests/` 配下に `test_<モジュール名>.py` で置く(例: `core/color.py` → `tests/core/test_color.py`) +- 同梱データは `data/` に置き Git 管理する.ユーザーが実行時に選択するファイル(変換行列 CSV・舌画像)はリポジトリに含めない diff --git a/.claude/rules/testing.md b/.claude/rules/testing.md new file mode 100644 index 0000000..6186080 --- /dev/null +++ b/.claude/rules/testing.md @@ -0,0 +1,29 @@ +--- +paths: ["tests/**", "**/test_*.py"] +--- + +# テスト方針 (Testing Policy) + +テストを作成・実行するときは本方針に従うこと. + +## 基本方針 (Basic Policy) + +- テストフレームワークは **pytest**.実行は `uv run pytest` +- テスト対象の中心は `core/`(診断ロジック).**GUI の自動テストは書かない**(画面は人間が動作確認する.CLAUDE.md「手動確認が必要な作業」参照) +- 旧実装との**結果同一性**が本プロジェクトの成功基準(PLAN_01)のため,回帰テストを最重視する + +## テストの種類 (Test Types) + +| 種類 | 対象 | 方針 | +| --- | --- | --- | +| 単体テスト | `core/` の各関数 | 数式(Lab 変換等)は手計算・既知値で検証する | +| 回帰テスト | 診断パイプライン全体 | 旧実装 exe で得た入出力ペア(RGB → 5 色スコア)を固定データとして照合する | +| 異常系テスト | CSV 読込・入力ガード | 不正形式・欠損ファイルでの例外を検証する | + +## 規則 (Rules) + +- テストファイルは `tests/` 配下に `test_<モジュール名>.py`(配置は project-structure.md 参照) +- テスト用の固定データ(サンプル CSV・期待値)は `tests/fixtures/` に置く +- SVM のような学習を伴うテストも**乱数シードに依存させない**(現行 SVM は決定的.非決定的な挙動が見つかった場合は仕様として記録する) +- モックは外部境界(ファイルダイアログ等)のみに使う.`core/` 内部はモックせず実物で検証する +- テストが遅くなったら(30 秒超),SVM 学習系のテストに `slow` マーカーを付けて分離する diff --git a/CLAUDE.md b/CLAUDE.md index 978cd33..3c32d18 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ ## 開発進捗 -最新: /setup フェーズ 4(仕様設計)まで完了.次はフェーズ 5(規約整備) +最新: /setup フェーズ 5(規約整備)まで完了.次はフェーズ 6(開発計画) ※ 本欄は**最新ステップ 1 行のみ上書き更新**.詳細な進捗履歴(動機・設計判断・失敗パターン)は [docs/PROGRESS.md](docs/PROGRESS.md) に追記する.運用ルールは `.claude/rules/progress-log.md` を参照(該当ファイル編集時に自動ロードされる). ## 必須ルール(コード実装時) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 13fa92a..a250dcb 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -16,3 +16,4 @@ - [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 自動テストは書かない方針