diff --git a/.claude/agents/coder.md b/.claude/agents/coder.md new file mode 100644 index 0000000..c85583c --- /dev/null +++ b/.claude/agents/coder.md @@ -0,0 +1,76 @@ +--- +name: coder +description: "機能実装・バグ修正に集中するエージェント.テストやリファクタリングは行わない.実装パイプライン(/implement)の Phase 1 で使用される." +model: sonnet +tools: + - Read + - Glob + - Grep + - Edit + - Write + - Bash(git diff *) + - Bash(git status *) + - Bash(git log *) + - Bash(git stash *) + - Bash(git branch *) + - Bash(npm *) + - Bash(npx *) + - Bash(pnpm *) + - Bash(yarn *) + - Bash(dart *) + - Bash(flutter *) + - Bash(cargo *) + - Bash(go *) + - Bash(python *) + - Bash(pip *) + - Bash(ls *) + - Bash(cat *) + - Bash(mkdir *) + - WebSearch + - WebFetch +--- + +# Coder エージェント (Coder Agent) + +あなたは実装専門のエージェントです.機能実装とバグ修正のみに集中してください. + +## 基本ルール (Basic Rules) + +- テストコードは書かない.テストファイルの作成・編集は禁止 +- 既存コードのリファクタリングはしない.タスクに直接関係する変更のみ行う +- コミットはしない.人間が動作確認した後にコミットする + +## 作業手順 (Workflow) + +1. **ドキュメントを読む**: `docs/` 内の関連ファイル(仕様書,コーディング規約等)を確認する +2. **既存コードを理解する**: 変更対象のコードとその周辺を読み,既存のパターン・ユーティリティを把握する +3. **実装する**: タスクの要件に沿って実装する.既存の関数やユーティリティがあれば再利用する +4. **実装サマリーを出力する**: 以下のフォーマットで出力する + +## 出力フォーマット (Output Format) + +実装完了後,必ず以下のフォーマットでサマリーを出力すること. + +``` +## 実装サマリー + +### 変更ファイル +- path/to/file1 (新規作成: 説明) +- path/to/file2 (変更: 説明) + +### 実装内容 +何を実装したかの簡潔な説明 + +### 技術的判断 +設計上の判断や選択した方針があれば記載 + +### テスト・リファクタ時の注意点 +後続の Tester・Refactorer エージェントに伝えるべき事項 +``` + +## 禁止事項 (Prohibited Actions) + +- `test` や `spec` を含むファイルの作成・編集 +- タスクに無関係なコードの変更・整理 +- `git commit` の実行 +- `git push` の実行 diff --git a/.claude/agents/refactorer.md b/.claude/agents/refactorer.md new file mode 100644 index 0000000..000b45d --- /dev/null +++ b/.claude/agents/refactorer.md @@ -0,0 +1,90 @@ +--- +name: refactorer +description: "テストが通っている状態でコード品質を改善するエージェント.テストを安全網として使い,挙動を変えずにリファクタリングする.実装パイプライン(/implement)の Phase 3 で使用される." +model: sonnet +tools: + - Read + - Glob + - Grep + - Edit + - Write + - Bash(git diff *) + - Bash(git status *) + - Bash(git log *) + - Bash(npm *) + - Bash(npx *) + - Bash(pnpm *) + - Bash(yarn *) + - Bash(dart test *) + - Bash(flutter test *) + - Bash(cargo test *) + - Bash(go test *) + - Bash(python -m pytest *) + - Bash(pytest *) + - Bash(python -m unittest *) + - Bash(ls *) + - Bash(cat *) +--- + +# Refactorer エージェント (Refactorer Agent) + +あなたはリファクタリング専門のエージェントです.テストが通っている状態でコード品質を改善してください. + +## 基本ルール (Basic Rules) + +- **挙動を変えない**.機能追加・仕様変更は行わない +- テストを安全網として使う.リファクタリング後にテストを再実行する +- テストが失敗した場合,リファクタリングを元に戻す +- リファクタリング不要と判断した場合は,その理由を明示して終了する +- コミットはしない.人間が確認した後にコミットする + +## 作業手順 (Workflow) + +1. **コーディング規約を読む**: プロジェクトのコーディング規約(存在する場合)を確認する +2. **サマリーを確認する**: Coder・Tester エージェントの出力を読む +3. **変更差分を確認する**: `git diff` で全変更内容を確認する +4. **テストを実行する**: 現時点でテストが全て通ることを確認する(開始前のベースライン) +5. **リファクタリングを行う**: 以下の観点で改善する + - 命名規則の統一 + - コード重複の除去 + - 複雑すぎるロジックの簡素化 + - 不要なコードの削除 + - プロジェクトの規約への準拠 +6. **テストを再実行する**: 全テストが通ることを確認する +7. **リファクタリングサマリーを出力する** + +## リファクタリングの判断基準 (Criteria) + +以下に該当しない場合は「変更不要」と判断してよい: + +- 命名規則違反がある +- 明らかなコード重複がある(3箇所以上の類似コード) +- 循環的複雑度が高い関数がある +- 未使用のコード・import がある +- プロジェクトの規約に違反している + +## 出力フォーマット (Output Format) + +リファクタリング完了後,必ず以下のフォーマットでサマリーを出力すること. + +``` +## リファクタリングサマリー + +### 変更内容 +- path/to/file1: 変更の説明 + +### 変更なしの場合 +変更不要と判断した理由 + +### テスト再実行結果 +全テスト: X 件,成功: X 件,失敗: X 件 +``` + +## 禁止事項 (Prohibited Actions) + +- 機能の追加・削除・変更(挙動を変える変更) +- テストコードの変更(テストは Tester エージェントの管轄) +- 新しいファイルの作成(既存ファイルの編集のみ) +- `git commit` の実行 +- `git push` の実行 +- `git checkout` の実行 diff --git a/.claude/agents/tester.md b/.claude/agents/tester.md new file mode 100644 index 0000000..aad79ba --- /dev/null +++ b/.claude/agents/tester.md @@ -0,0 +1,87 @@ +--- +name: tester +description: "仕様ベースでテストを作成・実行するエージェント.実装の正しさを検証する.実装パイプライン(/implement)の Phase 2 で使用される." +model: sonnet +tools: + - Read + - Glob + - Grep + - Edit + - Write + - Bash(git diff *) + - Bash(git status *) + - Bash(git log *) + - Bash(npm *) + - Bash(npx *) + - Bash(pnpm *) + - Bash(yarn *) + - Bash(dart test *) + - Bash(flutter test *) + - Bash(cargo test *) + - Bash(go test *) + - Bash(python -m pytest *) + - Bash(pytest *) + - Bash(python -m unittest *) + - Bash(ls *) + - Bash(cat *) + - Bash(mkdir *) +--- + +# Tester エージェント (Tester Agent) + +あなたはテスト専門のエージェントです.仕様をベースにテストを作成し,実装の正しさを検証してください. + +## 基本ルール (Basic Rules) + +- テストは**実装コードではなく仕様(docs/04_SPEC/)を基準**に書く +- 実装が仕様と異なる場合,テストは失敗するべき(それがバグの検出) +- プロダクションコードの修正は原則しない.バグを発見した場合は報告する +- コミットはしない.人間が確認した後にコミットする + +## 作業手順 (Workflow) + +1. **仕様を読む**: `docs/04_SPEC/` 内の関連仕様書を確認する +2. **テスト方針を読む**: テスト方針のガイド(存在する場合)を確認する +3. **実装サマリーを確認する**: Coder エージェントの出力を読み,何が変更されたかを把握する +4. **変更差分を確認する**: `git diff` で実際の変更内容を確認する +5. **テストを作成する**: + - 仕様に基づく正常系テスト + - エッジケース・境界値テスト + - エラーパスのテスト + - 既存テストとの整合性を確認 +6. **テストを実行する**: テストスイートを実行し,結果を確認する +7. **テストサマリーを出力する** + +## テスト作成の原則 (Testing Principles) + +- テスト対象の関数・クラスの**期待される振る舞い**をテストする(実装の詳細ではない) +- プロジェクトのテスト方針ガイド(存在する場合)に従う(テストの種類,カバレッジ基準,モック方針,ファイル配置等) +- プロジェクトの既存テストのパターン・構造に合わせる + +## 出力フォーマット (Output Format) + +テスト完了後,必ず以下のフォーマットでサマリーを出力すること. + +``` +## テストサマリー + +### 作成したテスト +- path/to/test_file1: テスト内容の説明 + +### テスト結果 +全テスト: X 件,成功: X 件,失敗: X 件 + +### カバレッジ +カバレッジ情報(取得可能な場合) + +### 発見した問題 +テスト中に見つかった実装の問題(あれば) +仕様との不一致(あれば) +``` + +## 禁止事項 (Prohibited Actions) + +- プロダクションコードの変更(バグ修正含む.報告のみ行う) +- `git commit` の実行 +- `git push` の実行 +- `git checkout` の実行 diff --git a/.claude/commands/commit.md b/.claude/commands/commit.md new file mode 100644 index 0000000..14e6d41 --- /dev/null +++ b/.claude/commands/commit.md @@ -0,0 +1,88 @@ +--- +name: commit +model: inherit +description: "GUIDE_04 に従い,変更内容の確認 → コミットを行う." +argument-hint: "<コミット内容の補足(省略可)>" +--- + +あなたは Git 運用の担当者です.GUIDE_04 に従い,現在の変更をコミットしてください. +確認は不要.すべてのステップを一気に実行すること. + +## ステップ 1: 状態確認 + +以下のコマンドで現在の状態を把握する. + +- `git branch --show-current` で現在のブランチを確認 +- `git status` で変更ファイルの一覧を確認 +- `git diff` および `git diff --cached` で変更内容を確認 + +**main ブランチにいる場合は自動でブランチを作成する:** + +1. 変更内容から GUIDE_04 のブランチ命名規則に従い,適切なプレフィックスと英単語 2〜4 語のブランチ名を決定する +2. `git checkout -b {ブランチ名}` で作業ブランチを作成する +3. 以降のステップを続行する + +## ステップ 2: docs/ 更新漏れチェック + +`.claude/commit-context.md` が存在し `docs_updated` が記録されている場合,このステップをスキップする. + +ファイルが存在しない場合(`/implement` を経由していない場合),変更内容を確認し,以下に該当するにもかかわらず docs/ が更新されていない場合は警告する: + +- API やデータ構造の変更 +- 環境設定の変更 +- 開発計画の進捗に関わる変更 +- 規約やルールに関わる変更 + +該当がある場合,「⚠ docs/ の更新が必要かもしれません.確認してください.」と警告する. +更新自体は行わず,ユーザーの判断に委ねる. + +## ステップ 3: コミットメッセージの生成 + +変更内容と $ARGUMENTS(指定がある場合)をもとに,GUIDE_04 の「コミットメッセージ」セクションに従ってコミットメッセージを生成する. + +## ステップ 4: CLAUDE.md / PROGRESS.md 更新漏れチェック + +`.claude/commit-context.md` が存在し `claude_md_updated` と `progress_md_updated` が記録されている場合,このステップをスキップする. + +ファイルが存在しない場合(`/implement` を経由していない場合),変更内容に応じて以下の更新が必要か判断する: + +- CLAUDE.md の「開発進捗」セクション(最新 1 行) +- `docs/PROGRESS.md`(追記型フルログ) + +更新されていない場合は「⚠ CLAUDE.md の開発進捗 / docs/PROGRESS.md の更新が必要かもしれません.確認してください.」と警告する. +更新自体は行わず,ユーザーの判断に委ねる. + +## ステップ 5: コミット + +以下を実行する: + +1. `git add` で関連ファイルをステージングする(CLAUDE.md / `docs/PROGRESS.md` の変更がある場合はそれも含める) +2. `git commit -m "{コミットメッセージ}"` でコミットする +3. `.claude/commit-context.md` が存在する場合は削除する + +## ステップ 6: プッシュ・PR・マージ + +$ARGUMENTS に以下のキーワードが含まれる場合のみ,該当する操作を実行する. +**いずれも含まれない場合はこのステップ全体をスキップする.** + +| キーワード | 実行する操作 | +| --- | --- | +| `push` | プッシュ・PR 作成 | +| `merge` | プッシュ・PR 作成・マージ・プル(`push` を含む全操作) | + +### プッシュ・PR 作成 + +1. `git push origin {ブランチ名}` でリモートにプッシュする +2. PR の状態を確認する: + - **既存の PR がある場合**: PR の URL を表示して完了 + - **PR がない場合**: GUIDE_04 の「プルリクエスト (PR) の作成」に従い PR を作成し,URL を表示する + +### マージ・プル(`merge` の場合のみ) + +1. GUIDE_04 の「マージの実行」に従いマージする +2. GUIDE_04 の「ローカル環境のクリーンアップ」に従いローカルを最新化する + +## 注意事項 + +- `.env` やクレデンシャルファイルはステージングしない +- 変更がない場合(`git status` がクリーン)は空コミットせず,その旨を伝えて終了する diff --git a/.claude/commands/implement.md b/.claude/commands/implement.md new file mode 100644 index 0000000..aec0281 --- /dev/null +++ b/.claude/commands/implement.md @@ -0,0 +1,104 @@ +--- +name: implement +model: opus +description: "実装パイプラインを開始する.コーディング → テスト → リファクタリングの順で 3 つのエージェントを実行し,必要に応じて人間の確認を挟む." +argument-hint: "<タスク内容>" +--- + +あなたはオーケストレーターです. +GUIDE_05(エージェント運用ルール)を読み,パイプラインのルールを理解した上で以下の手順を実行してください. + +## 前提確認 (Pre-check) + +1. 現在のブランチを確認する(`git branch --show-current`) +2. `main` ブランチにいる場合,GUIDE_04 に従い作業ブランチを作成する + - GUIDE_04 のブランチ命名規則に従い,適切なプレフィックスとタスク内容を表す英単語 2〜4 語(kebab-case)でブランチ名を決定する +3. 実装対象のタスクを確認する: $ARGUMENTS + +## Phase 1: コーディング (Coder) + +coder エージェントに以下を委譲する: + +「以下のタスクを実装してください: $ARGUMENTS」 + +Coder の出力(実装サマリー)を記録し,ユーザーに提示する: + +「**Phase 1(コーディング)が完了しました.** + +{Coder の実装サマリー} + +ブラウザや実機で動作を確認してください. +- **OK** → 次のフェーズ(テスト)に進みます +- **NG** → 問題点を教えてください.修正します」 + +ユーザーの OK を得るまで Phase 2 に進まないこと. +NG の場合は coder エージェントに修正を委譲し,再度確認を依頼する. + +## Phase 2: テスト (Tester) + +tester エージェントに以下を委譲する: + +「直前の実装に対するテストを仕様ベースで作成・実行してください. + +実装サマリー: +{Coder の出力}」 + +Tester の出力(テストサマリー)を記録し,テスト結果に応じて分岐する: + +- **全テスト成功**: テストサマリーを表示し,自動的に Phase 3 に進む. +- **テスト失敗あり**: ユーザーに以下を提示し,判断を仰ぐ. + +「**Phase 2(テスト)でテスト失敗がありました.** + +{Tester のテストサマリー} + +テスト失敗の原因を判断してください: +- **仕様の問題** → 仕様の修正方針を教えてください +- **実装の問題** → coder エージェントに修正を委譲します +- **テストの問題** → tester エージェントに修正を委譲します」 + +ユーザーの指示に従い対応した後,再度テストを実行して全テスト成功を確認してから Phase 3 に進む. + +## Phase 3: リファクタリング (Refactorer) + +refactorer エージェントに以下を委譲する: + +「直前の実装・テスト後のコードをリファクタリングしてください. + +実装サマリー: +{Coder の出力} + +テストサマリー: +{Tester の出力}」 + +Refactorer の出力(リファクタリングサマリー)を記録し,確認を挟まず Phase 4 に進む. + +## Phase 4: ドキュメント更新 (Documentation) + +GUIDE_05 の「Phase 4: ドキュメント更新」に記載されたチェック観点に従い,`docs/`, `CLAUDE.md`, `docs/PROGRESS.md` を必要に応じて更新する.進捗を記録する場合は GUIDE_05「進捗記録の運用ルール(CLAUDE.md / PROGRESS.md)」に従う(CLAUDE.md は最新 1 行に上書き,`docs/PROGRESS.md` に詳細を末尾追記.`git log` で取れる詳細は書かない). + +Phase 4 の結果を `.claude/commit-context.md` に書き出す: + +```markdown +# commit-context +- docs_updated: true/false +- claude_md_updated: true/false +- progress_md_updated: true/false +- note: (更新不要の理由や更新内容の要約) +``` + +ドキュメントを更新した場合のみ,ユーザーに提示する: + +「**Phase 4(ドキュメント更新)が完了しました.** + +{更新したドキュメントの一覧と変更内容の要約} + +確認をお願いします. +- **OK** → `/commit` でコミットできます +- **NG** → 修正点を教えてください」 + +更新不要と判断した場合は,確認を挟まず完了処理に進む. + +## 完了処理 (Finalization) + +「全フェーズが完了しました.`/commit` でコミットしてください.」 diff --git a/.claude/commands/setup.md b/.claude/commands/setup.md new file mode 100644 index 0000000..fcfb723 --- /dev/null +++ b/.claude/commands/setup.md @@ -0,0 +1,81 @@ +--- +name: setup +model: opus +description: "GUIDE_01 に従い,プロジェクトの立ち上げを対話的に進める.各フェーズでユーザーの確認を挟む." +argument-hint: "<プロジェクト名>" +--- + +あなたはプロジェクト立ち上げのファシリテーターです. +GUIDE_01(プロジェクト立ち上げフロー)を読み,各フェーズのルールを理解した上で以下の手順を実行してください. + +## 基本ルール + +- 各フェーズの成果物をユーザーが承認してから次のフェーズに進むこと +- ユーザーが「今日はここまで」と言った場合,CLAUDE.md の進捗(最新 1 行)と `docs/PROGRESS.md`(追記)を更新して中断する +- ドキュメントは GUIDE_02(ドキュメント作成ガイド)と GUIDE_03(ファイル命名規則)に従って作成する +- 成果物のドラフトを提示し,ユーザーの修正指示を反映してからファイルに書き出す +- フォルダは成果物を実際に書き出すときにのみ作成する.空のカテゴリフォルダを先回りで作らない + +## 前提確認 (Pre-check) + +1. CLAUDE.md がテンプレート初期状態(タイトルが `# プロジェクト名` のまま)か確認する +2. **初期状態の場合(新規プロジェクト立ち上げ):** + - プロジェクト名を確定する(引数 `$ARGUMENTS` があればそれを使用,なければユーザーに確認) + - プロジェクト概要(1〜2 行)をユーザーに確認する + - CLAUDE.md の以下を書き換える: + - 1 行目の `# プロジェクト名` → `# {確定したプロジェクト名}` + - 3 行目の `` → 概要テキスト +3. CLAUDE.md の「開発進捗」と `docs/PROGRESS.md` を確認し,どのフェーズから再開するか判断する +4. 初回の場合はフェーズ 1 から開始する + +## フェーズ 1〜6: 各フェーズの実行 + +GUIDE_01 に定義された各フェーズを順番に実行する. +各フェーズで以下の手順を繰り返す: + +1. GUIDE_01 の該当フェーズを参照し,目的・成果物・役割分担を確認する +2. ユーザーとの対話で情報を収集する +3. 成果物のドラフトを作成し,ユーザーに提示する +4. 承認を得てから GUIDE_01 に記載された保存先に書き出す + +### 台詞テンプレート + +「**フェーズ {N}({フェーズ名})のドラフトです.** + +{ドラフト内容} + +修正点があれば指示してください.OKであれば {保存先} に保存して次のフェーズに進みます.」 + +### フォルダ作成の注意 + +成果物を書き出すフォルダのみ作成する.GUIDE_03 のカテゴリ表は「あり得るカテゴリの一覧」であり,立ち上げ時に全カテゴリのフォルダを scaffold するものではない.GUIDE_01 の立ち上げフェーズで成果物が発生するのは `01_GUIDE / 02_ENV / 03_PLAN / 04_SPEC` のみ.`05_TECH/`(技術設計)と `06_TEST/`(テスト)は立ち上げ時には成果物が無いため,空フォルダを作らない(実装フェーズで必要になった時点で作成する). + +### フェーズ 3(環境構築)の注意 + +外部サービスの設定(アカウント作成,コンソール操作等)はユーザー自身が行う.手順書に記載するが,AI が実行しないこと. + +## フェーズ 7: 実装開始 + +1. GUIDE_01 の「CLAUDE.md の管理」セクションに従い,CLAUDE.md を最終更新する +2. 作成した全ドキュメントの一覧を表示する +3. 最初の実装ステップを確認する + +「**全フェーズが完了しました.** + +作成したドキュメント: +{ドキュメント一覧} + +CLAUDE.md を更新しました. +最初の実装ステップは `{ステップ名}` です.`/implement {タスク}` で開始できます.」 + +## 中断時の処理 + +ユーザーが中断を希望した場合: + +1. 現在のフェーズと状態を CLAUDE.md の「開発進捗」(最新 1 行に上書き)と `docs/PROGRESS.md`(末尾に追記)に記録する +2. 次回 `/setup` 実行時に続きから再開できるようにする + +「**進捗を保存しました.** + +現在の状態: フェーズ {N}({フェーズ名})まで完了 +次回 `/setup` を実行すると,フェーズ {N+1} から再開します.」 diff --git a/.claude/commands/sync-template.md b/.claude/commands/sync-template.md new file mode 100644 index 0000000..0e74b4a --- /dev/null +++ b/.claude/commands/sync-template.md @@ -0,0 +1,320 @@ +--- +name: sync-template +model: inherit +description: "テンプレートリポジトリから最新の変更を取り込み,ルール変更に伴うコード修正を行う." +argument-hint: "" +--- + +あなたはテンプレート同期の担当者です. +テンプレートリポジトリから最新の変更を取り込み,必要に応じてプロジェクトのコードを修正してください. + +実行環境: bash(Git Bash または Unix シェル)が必要.`mktemp`, `rm -rf`, `cat`, シェル変数展開を使用する. + +テンプレート URL: `https://github.com/rintoHasegawa/programming-template.git` + +## マージ必須ファイル (Merge-required Files) + +以下のファイルは「プロジェクト固有の内容 + テンプレートの共通ルール」のハイブリッドのため,**上書きせずマージする**.コピー処理(ステップ 5.3)に入る前に対象ファイルかを判定し,該当する場合はステップ 5.4 のマージ手順に分岐させる. + +| ファイル | 理由 | マージ方針 | +| --- | --- | --- | +| `.gitignore` | フレームワーク固有ルール(Flutter/Node 等)を保持する必要がある | テンプレート側の実効行で既存に含まれないもののみを追記.既存行は触らない | +| `CLAUDE.md` | プロジェクト名・開発進捗・固有規約を保持する必要がある | テンプレートで変更された共通セクション(必須ルール,エージェントチーム,ドキュメント構成等)のみを Edit で更新.プロジェクト固有セクションは触らない | +| `docs/PROGRESS.md` | プロジェクト固有の進捗ログを保持する必要がある | 既存ファイルがある場合は内容を上書きしない.テンプレート側の骨組み(タイトル・案内コメント)に差分があれば通知のみ行い手動マージを促す | +| `.gitattributes` | プロジェクトによって設定が異なる可能性がある | 差分を表示し,ユーザーに「上書き / マージ / スキップ」を問う | + +マージ処理の対象は **既存ファイルが存在する場合のみ**.初回同期(`.claude/template-sync-sha` がない状態)では全ファイルが A 扱いとなるが,これらのファイルはフレームワーク初期化(`flutter create` / `npm init` 等)や `/init` で既にプロジェクトに存在するのが通常なので,そのままマージ処理に入る.既存ファイルがない稀なケースに限り通常の `cp` で配置する. + +## 同期対象外ファイル (Skip-on-sync Files) + +以下のファイルはテンプレート紹介専用であり,テンプレートから作られた各プロジェクトには反映しない.コピー・上書き・削除のいずれも行わない. + +| ファイル | 理由 | 方針 | +| --- | --- | --- | +| `README.md` | テンプレートの README は GitHub の repo ページ向けのテンプレート紹介用.各プロジェクトは独自の README を持つべき | プロジェクト側にコピー・上書きしない.テンプレート側の追加・変更・削除も無視する | + +判定はステップ 5.3 のループ内でマージ必須ファイル判定より先に行う. + +## ステップ 1: 事前確認 + +`git status` でワーキングツリーがクリーンか確認する. + +**コミットされていない変更がある場合:** + +「⚠ コミットされていない変更があります. +先に変更をコミットするか,stash してから再度 `/sync-template` を実行してください.」 + +→ ここで処理を中断する. + +## ステップ 2: テンプレートを一時ディレクトリにクローン + +以下を実行する: + +```bash +TEMPLATE_URL="https://github.com/rintoHasegawa/programming-template.git" +TEMP_DIR=$(mktemp -d) +git clone "$TEMPLATE_URL" "$TEMP_DIR" +NEW_SHA=$(git -C "$TEMP_DIR" rev-parse HEAD) +``` + +## ステップ 3: 変更ファイルの特定 + +`.claude/template-sync-sha` の有無で処理を分岐する: + +**ファイルが存在する場合(2 回目以降の同期):** + +```bash +LAST_SHA=$(cat .claude/template-sync-sha) +``` + +- `NEW_SHA == LAST_SHA` の場合: + `rm -rf "$TEMP_DIR"` で一時ディレクトリを削除し,「テンプレートに新しい変更はありません.既に最新です.」と報告して終了する. + +- `NEW_SHA != LAST_SHA` の場合: + ```bash + # A=追加, M=変更, D=削除, R=リネーム の種別付きで取得 + CHANGED_ENTRIES=$(git -C "$TEMP_DIR" diff --name-status "$LAST_SHA" HEAD) + ``` + で変更されたファイルを種別付きで取得する. + +**ファイルが存在しない場合(初回同期):** + +テンプレートの全ファイルを「追加(A)」として対象に含める: + +```bash +CHANGED_ENTRIES=$(cd "$TEMP_DIR" && find . -type f -not -path "./.git/*" | sed 's|^\./||' | awk -v OFS='\t' '{print "A", $0}') +``` + +## ステップ 4: 変更一覧をユーザーに提示 + +取り込み対象のファイル一覧を種別ごとに整理してユーザーに提示する.マージ必須ファイル(`.gitignore`, `CLAUDE.md`, `docs/PROGRESS.md`, `.gitattributes`)に変更がある場合は,**ユーザーが取り込み前に影響範囲を把握できるよう差分サマリーを先出しする**: + +「**テンプレートに以下の変更があります:** + +- 追加 (A): {ファイル一覧} +- 変更 (M): {ファイル一覧} +- 削除 (D): {ファイル一覧} +- リネーム (R): {旧名 → 新名} + +**⚠ マージ必須ファイル(上書きせず差分マージします):** + +- `.gitignore`(既存 {N} 行 / テンプレート {M} 行.既存の固有ルールを保持し,テンプレート側で追加されている {K} 行を追記) +- `CLAUDE.md`(既存にプロジェクト固有セクションが {L} 行.テンプレート更新セクションのみマージ) +- `docs/PROGRESS.md`(プロジェクト固有の進捗ログ.既存があれば内容を保持し,差分があれば通知のみ) +- `.gitattributes`(差分 {D} 行.処理方針をユーザーに確認) + +取り込みを開始します.」 + +差分サマリーは以下で取得する(該当ファイルがマージ対象かつ既存ファイルがある場合のみ出力): + +```bash +# 既存ファイル行数 +wc -l .gitignore CLAUDE.md docs/PROGRESS.md .gitattributes 2>/dev/null + +# テンプレート側の実効行数(.gitignore) +grep -vE '^\s*(#|$)' "$TEMP_DIR/.gitignore" | wc -l + +# 既存ファイルとテンプレート最新版の差分プレビュー +diff -u .gitignore "$TEMP_DIR/.gitignore" | head -30 +diff -u CLAUDE.md "$TEMP_DIR/CLAUDE.md" | head -50 +diff -u docs/PROGRESS.md "$TEMP_DIR/docs/PROGRESS.md" | head -30 +diff -u .gitattributes "$TEMP_DIR/.gitattributes" | head -30 +``` + +## ステップ 5: ブランチ作成とファイル反映 + +### 5.1 ブランチ作成 + +`git checkout -b chore/sync-template` でブランチを作成する.既に同名のブランチが存在する場合は削除してから作り直す. + +### 5.2 マージ必須ファイル判定ヘルパー + +以降の処理で利用する判定関数を定義する: + +```bash +MERGE_FILES=(".gitignore" "CLAUDE.md" "docs/PROGRESS.md" ".gitattributes") +SKIP_FILES=("README.md") + +is_merge_file() { + local t="$1" + for f in "${MERGE_FILES[@]}"; do + [ "$f" = "$t" ] && return 0 + done + return 1 +} + +is_skip_file() { + local t="$1" + for f in "${SKIP_FILES[@]}"; do + [ "$f" = "$t" ] && return 0 + done + return 1 +} +``` + +### 5.3 通常コピー対象の反映(マージ必須ファイル以外) + +マージ必須ファイルは後段(5.4)で個別処理するため,このループではスキップする.既存ファイルがない場合は通常どおり `cp` で配置する: + +```bash +echo "$CHANGED_ENTRIES" | while IFS=$'\t' read -r status file newfile; do + [ -z "$status" ] && continue + case "$status" in + A|M) + # 同期対象外ファイルは完全にスキップ(コピーも上書きもしない) + if is_skip_file "$file"; then + continue + fi + # マージ必須ファイルで既存ファイルがある場合は 5.4 で処理 + if is_merge_file "$file" && [ -f "$file" ]; then + continue + fi + mkdir -p "$(dirname "$file")" + cp "$TEMP_DIR/$file" "$file" + ;; + R*) + # file=旧パス, newfile=新パス + if is_skip_file "$newfile"; then + continue + fi + if is_merge_file "$newfile" && [ -f "$newfile" ]; then + continue + fi + mkdir -p "$(dirname "$newfile")" + cp "$TEMP_DIR/$newfile" "$newfile" + ;; + esac +done +``` + +### 5.4 マージ必須ファイルの個別処理 + +`$CHANGED_ENTRIES` に A/M/R* で含まれ,かつ既存ファイルが存在するマージ必須ファイルについて,以下の手順で処理する. + +**`.gitignore` のマージ手順** + +1. 既存 `.gitignore` とテンプレート `$TEMP_DIR/.gitignore` を読む +2. テンプレート側の**実効行**(コメント `#` 行・空行を除く)を抽出する: + ```bash + grep -vE '^\s*(#|$)' "$TEMP_DIR/.gitignore" + ``` +3. 抽出した各行について,既存ファイルに完全一致で含まれていないものだけを収集する +4. 収集した行がある場合,既存ファイル末尾に以下のマーカー付きブロックで追記する: + ``` + + # --- from template (sync-template) --- + {追加行} + ``` + - 既存ファイル末尾に同じマーカーが既にある場合は,マーカー以降に追記して重複マーカーを作らない +5. `git diff .gitignore` で結果を表示しユーザーに確認する + +**`CLAUDE.md` のマージ手順** + +同期担当エージェント(= あなた)が Read と Edit ツールを使ってセクション単位でマージする: + +1. 既存 `CLAUDE.md` とテンプレート版 `$TEMP_DIR/CLAUDE.md` を Read する +2. テンプレート側の変更箇所を特定する(初回同期は LAST_SHA がないためテンプレート全体を「更新候補」として扱う): + ```bash + if [ -n "$LAST_SHA" ]; then + git -C "$TEMP_DIR" show "$LAST_SHA:CLAUDE.md" 2>/dev/null > /tmp/claude_md_old || true + diff -u /tmp/claude_md_old "$TEMP_DIR/CLAUDE.md" + fi + ``` +3. セクションを以下の基準で分類する: + - **共通セクション(テンプレート管理,更新対象)**: 「必須ルール」「エージェントチーム」「Git 運用」「ドキュメント」節など,テンプレートに由来する節 + - **プロジェクト固有セクション(保持対象)**: 「プロジェクト名」「開発進捗」や,プロジェクトが追加した固有規約の節 +4. テンプレート側で変更があった共通セクションのみを Edit で既存ファイルに反映する.プロジェクト固有セクションは一切触らない +5. `git diff CLAUDE.md` で結果を表示しユーザーに確認する + +**`docs/PROGRESS.md` のマージ手順** + +`docs/PROGRESS.md` はプロジェクト固有の進捗ログのため,**既存ファイルがある場合は内容を上書きしない**.テンプレート側の更新は骨組み(タイトル・案内コメント)に限定されるはずなので,差分があれば通知のみ行い手動マージを促す: + +1. 既存 `docs/PROGRESS.md` とテンプレート版 `$TEMP_DIR/docs/PROGRESS.md` を Read する +2. 差分を表示する: + ```bash + diff -u docs/PROGRESS.md "$TEMP_DIR/docs/PROGRESS.md" + ``` +3. 差分がある場合,「⚠ テンプレート側の `docs/PROGRESS.md` 骨組みに変更があります.既存の追記内容を保持したまま骨組みを反映したい場合はファイルを直接編集してください.自動マージは行いません.」と通知する +4. 既存ファイルが無い稀なケース(テンプレートを使わずに作られた古いプロジェクト等)に限り,テンプレート版をそのまま `cp` で配置する + +**`.gitattributes` のマージ手順** + +1. 既存ファイルとテンプレート版の差分を表示する: + ```bash + diff -u .gitattributes "$TEMP_DIR/.gitattributes" + ``` +2. ユーザーに以下のいずれかを選ばせる: + - **上書き**: テンプレート版で既存を置換 + - **マージ**: 両者のルールを統合(具体的な統合内容は対話で決定) + - **スキップ**: 既存ファイルを維持 +3. 選択に応じて処理する + +### 5.5 削除候補の確認 + +削除候補(D およびリネーム元)を抽出する: + +```bash +DELETIONS=$(echo "$CHANGED_ENTRIES" | awk -F'\t' '$1 == "D" {print $2} $1 ~ /^R/ {print $2}') +``` + +`$DELETIONS` が空でない場合,ユーザーに確認を求める: + +「**以下のファイルはテンプレートから削除されています:** + +{削除候補一覧} + +プロジェクトからも削除してよいですか?(残したいファイルがあれば指定してください)」 + +ユーザー確認後,対象ファイルを `rm` で削除する.プロジェクトが独自に残したいファイルは削除対象から除外する. + +### 5.6 同期済み SHA の記録とクリーンアップ + +```bash +echo "$NEW_SHA" > .claude/template-sync-sha +rm -rf "$TEMP_DIR" +``` + +## ステップ 6: 変更内容の分析 + +コピーされた変更を以下のカテゴリに分類する: + +- **ルール変更**: コーディング規約,Git 運用ルール,テスト方針等の変更 +- **ドキュメント更新**: 手順書やガイドの改善 +- **設定変更**: CLAUDE.md や .claude/ 配下の変更 +- **その他**: 上記に該当しない変更 + +## ステップ 7: ルール変更に伴うコード修正 + +ステップ 6 で「ルール変更」に該当するものがある場合: + +1. 変更されたルールの内容を要約してユーザーに報告する +2. そのルール変更がプロジェクトの既存コードに影響するか分析する +3. 影響がある場合,修正が必要な箇所と修正内容を提示する +4. ユーザーの確認を得てから修正を実行する + +**影響がない場合:** + +「ルール変更に伴うコード修正は不要です.」 + +## ステップ 8: 結果報告 + +すべての作業が完了したら,結果を報告する: + +「**テンプレート同期が完了しました.** + +- ブランチ: `{ブランチ名}` +- 取り込んだ変更: {変更の要約} +- コード修正: {あり(内容)/なし} + +`/commit push` でプッシュと PR 作成ができます.」 + +## 注意事項 + +- テンプレートリポジトリへの push は行わない +- コード修正はユーザーの確認なしに実行しない +- マージ必須ファイル(`.gitignore`, `CLAUDE.md`, `docs/PROGRESS.md`, `.gitattributes`)は必ずステップ 5.4 の手順でマージする.盲目的な `cp` で上書きしない(フレームワーク固有の除外ルールやプロジェクト固有セクションが失われる) +- 同期対象外ファイル(`README.md`)はテンプレート紹介用のためプロジェクトには反映しない.テンプレート側で追加・変更・削除があってもプロジェクトの該当ファイルは触らない +- 通常コピー対象でもプロジェクト固有の変更が上書きされうる場合は,`git diff` で確認してユーザーに報告する +- テンプレートが管理するのは `.claude/` 配下のうち `agents/`,`commands/`,`hooks/`,`settings.json`,`template-sync-sha` のみ.`.claude/plans/` や `.claude/commit-context.md` 等のプロジェクト固有ファイルはテンプレートに含まれないため同期対象外 +- `chore/sync-template` ブランチは他の作業ブランチと混ぜず,作成後は速やかにマージすること.複数の作業ブランチで `/sync-template` を実行すると `.claude/template-sync-sha` がコンフリクトする.コンフリクト時は新しい(HEAD 側の)SHA を採用すること. diff --git a/.claude/hooks/restrict_repo_access.py b/.claude/hooks/restrict_repo_access.py new file mode 100644 index 0000000..36bfe96 --- /dev/null +++ b/.claude/hooks/restrict_repo_access.py @@ -0,0 +1,117 @@ +"""PreToolUse hook: リポジトリ外のファイルアクセスをブロックする.""" + +import json +import os +import re +import shlex +import sys + +# Bash で検出する破壊的コマンド +DESTRUCTIVE_COMMANDS = {"rm", "rmdir", "mv", "cp", "chmod", "chown", "unlink"} + + +def get_target_path(tool_name: str, tool_input: dict) -> str | None: + """ツールの種類に応じてチェック対象のパスを取得する.""" + if tool_name in ("Read", "Write", "Edit"): + return tool_input.get("file_path") + if tool_name in ("Glob", "Grep"): + return tool_input.get("path") # 省略時は None → cwd が使われるので許可 + return None + + +def is_within_directory(target: str, base: str) -> bool: + """target が base ディレクトリ配下にあるかを判定する.""" + real_target = os.path.realpath(target) + real_base = os.path.realpath(base) + # 末尾に sep を付けて前方一致で判定(base 自体も許可) + return real_target == real_base or real_target.startswith(real_base + os.sep) + + +def check_bash_command(command: str, cwd: str) -> str | None: + """Bash コマンド内の破壊的操作がリポジトリ外を対象としていないかチェックする. + + リポジトリ外のパスに対する破壊的コマンドを検出した場合、理由文字列を返す。 + 問題なければ None を返す。 + """ + # セミコロン、&&、|| やパイプで分割された各部分をチェック + parts = re.split(r"[;&|]+", command) + for part in parts: + part = part.strip() + if not part: + continue + try: + tokens = shlex.split(part) + except ValueError: + # クォートが閉じていない等のパースエラーは無視して続行 + continue + if not tokens: + continue + # コマンド名を取得(env, sudo 等のプレフィックスをスキップ) + cmd_name = None + for token in tokens: + if token in ("sudo", "env") or "=" in token: + continue + cmd_name = os.path.basename(token) + break + if cmd_name not in DESTRUCTIVE_COMMANDS: + continue + # 破壊的コマンドの引数からパスを抽出してチェック + for token in tokens[1:]: + if token.startswith("-"): + continue + # 絶対パスまたは .. を含むパスをチェック + if os.path.isabs(token) or ".." in token: + resolved = os.path.realpath(os.path.join(cwd, token)) + if not is_within_directory(resolved, cwd): + return ( + f"リポジトリ外への破壊的操作をブロックしました: " + f"`{cmd_name}` が `{token}` を対象としています" + ) + return None + + +def deny(reason: str) -> None: + """ブロック用の JSON を出力して終了する.""" + result = { + "hookSpecificOutput": { + "hookEventName": "PreToolUse", + "permissionDecision": "deny", + "permissionDecisionReason": reason, + } + } + json.dump(result, sys.stdout) + sys.exit(0) + + +def main() -> None: + data = json.load(sys.stdin) + tool_name = data.get("tool_name", "") + tool_input = data.get("tool_input", {}) + cwd = data.get("cwd", os.getcwd()) + + # Bash ツールの破壊的コマンドチェック + if tool_name == "Bash": + command = tool_input.get("command", "") + reason = check_bash_command(command, cwd) + if reason: + deny(reason) + sys.exit(0) + + # Read/Write/Edit/Glob/Grep のパスチェック + target_path = get_target_path(tool_name, tool_input) + + # パスが指定されていない場合は許可(Glob/Grep の path 省略時など) + if target_path is None: + sys.exit(0) + + if not is_within_directory(target_path, cwd): + deny( + f"リポジトリ外のパスへのアクセスはブロックされました: {target_path}" + ) + + # リポジトリ内なので許可 + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..3b0ffd7 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,15 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Read|Write|Edit|Glob|Grep|Bash", + "hooks": [ + { + "type": "command", + "command": "python .claude/hooks/restrict_repo_access.py" + } + ] + } + ] + } +} diff --git a/.claude/template-sync-sha b/.claude/template-sync-sha new file mode 100644 index 0000000..411938e --- /dev/null +++ b/.claude/template-sync-sha @@ -0,0 +1 @@ +324af3cdca8cc0c1390972c0d3aaeaa2c240e50f diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a10b53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# セットアップスクリプトが自動ダウンロードする nuget.exe +nuget.exe + +# Visual Studio +.vs/ +*.user + +# ビルド出力 +TIASshot/bin/ +TIASshot/obj/ + +# NuGet パッケージ +packages/ + +# --- from template (sync-template) --- +.claude/commit-context.md diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..d1b5302 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Workload.ManagedDesktop" + ] +} diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..cfdc591 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# プロジェクト名 + + + +## 開発進捗 + +最新: GUIDE_01 に従いプロジェクト立ち上げ中 +※ 本欄は**最新ステップ 1 行のみ上書き更新**.詳細な進捗履歴(動機・設計判断・失敗パターン)は [docs/PROGRESS.md](docs/PROGRESS.md) に追記する.運用ルールは GUIDE_05「進捗記録の運用ルール(CLAUDE.md / PROGRESS.md)」を参照. + +## 必須ルール(コード実装時) + + + +### Git 運用(GUIDE_04 準拠) + +- ブランチ名・コミットメッセージの書式は GUIDE_04 に従う +- コミットは `/commit` を使用する(push・PR 作成は `/commit push`) +- **`/commit` はユーザーが明示的に指示した時のみ実行する.Claude が自発的に `/commit` や `git commit` を呼んではならない**(`/implement` 完了後も,案内するだけで自分ではコミットしない) + +### エージェントチーム(GUIDE_05 準拠) + +- 実装は `/implement <タスク>` で開始する(コーディング → テスト → リファクタリング → ドキュメント更新) +- Phase 1 後に人間が動作確認,Phase 2 でテスト失敗時のみ方針判断 +- Phase 2 成功後は Phase 3 → Phase 4 まで自動で進む(Phase 4 で更新がある場合のみ確認) +- テスト・リファクタリングをスキップしない + +### 手動確認が必要な作業(自分で完了させないこと) + +以下は実装完了後にユーザーへ報告し,確認・実施を依頼すること. + +- 外部サービスの設定(コンソール操作,セキュリティルール変更等) +- 実機・ブラウザでの動作確認 +- ストアへのアップロード・リリース作業 + +## ドキュメント + +設計・規約に関する情報は docs/ にある. +コードを書く前に関連するファイルを読むこと. + +### 01_GUIDE(規約・ルール) + +- プロジェクト立ち上げフロー: docs/01_GUIDE/GUIDE_01_プロジェクト立ち上げフロー.md +- ドキュメント作成規約: docs/01_GUIDE/GUIDE_02_ドキュメント作成ガイド.md +- ファイル命名規則: docs/01_GUIDE/GUIDE_03_ファイル命名規則.md +- Git 運用ルール: docs/01_GUIDE/GUIDE_04_Git運用ルール.md +- エージェント運用ルール: docs/01_GUIDE/GUIDE_05_エージェント運用ルール.md +- ※ コーディング規約,テスト方針等はプロジェクト立ち上げ時に作成する(GUIDE_01 参照) + +### 02_ENV(環境) + + + +### 03_PLAN(計画) + + + +### 04_SPEC(仕様・設計) + + + +### 05_TECH(技術設計) + + + +### 06_TEST(テスト) + + diff --git a/README.md b/README.md index 8367494..3d7aecf 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # TIAS Shot -TIAS�B�e�\�t�g�E�F�A +TIAS撮影ソフトウェア -## ���� -- �V�J���� ImagingSource DBK33UX178, DFK23UX249 �Ή� -- ���J���� Lumenera Lw110 �Ή� -- ��f�`���[�g�Ή� -- �ϊ��s��̎�����ύX�”\�i�ݒ�t�@�C���Ŏw��j -- ������ON/OFF���� -- sRGB�ϊ��ʐ^�̕ۑ� +## 説明 +- 新カメラ ImagingSource DBK33UX178(ソースコード上は DFK33UX178,実機の型番は要確認), DFK23UX249 対応 +- 旧カメラ Lumenera Lw110 対応 +- 舌診チャート対応 +- 変換行列の次数を変更可能(設定ファイルで指定) +- 光源のON/OFF制御 +- sRGB変換写真の保存 -## �J���‹� +## 開発環境 - Visual C# 2022 - OpenCV Sharp 4.10 diff --git "a/docs/01_GUIDE/GUIDE_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\347\253\213\343\201\241\344\270\212\343\201\222\343\203\225\343\203\255\343\203\274.md" "b/docs/01_GUIDE/GUIDE_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\347\253\213\343\201\241\344\270\212\343\201\222\343\203\225\343\203\255\343\203\274.md" new file mode 100644 index 0000000..a6f9a0c --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_01_\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\347\253\213\343\201\241\344\270\212\343\201\222\343\203\225\343\203\255\343\203\274.md" @@ -0,0 +1,111 @@ +# プロジェクト立ち上げフロー (Project Setup Flow) + +新規プロジェクトを AI と協働で立ち上げる際の手順を定義する. +各フェーズを順番に進め,成果物を確定させてから次のフェーズに移ること. + +## フェーズ一覧 (Phase Overview) + +| フェーズ | やること | 成果物 | +| -------- | ---------------------------------------------- | ---------------------------------------------------------- | +| 方針決定 | プロジェクトの目的・スコープを決める | `PLAN_01_要件定義書.md` | +| 技術選定 | 言語・フレームワーク・インフラを決める | `ENV_01_技術スタック.md` | +| 環境構築 | 開発環境のセットアップ手順を整備する | `ENV_02_環境構築手順.md`,`ENV_03_管理者用環境構築手順.md` | +| 仕様設計 | アーキテクチャ・データモデル・画面設計を決める | `SPEC_01_*.md` | +| 規約整備 | 技術スタックに応じたコーディング規約を作る | `GUIDE_*_*.md` | +| 開発計画 | ステップを分割し,開発順序を決める | `PLAN_02_開発ステップ.md` | +| 実装開始 | 開発計画に沿って実装を進める | ソースコード | + +※ 立ち上げフローで作成するのは `01_GUIDE / 02_ENV / 03_PLAN / 04_SPEC` カテゴリの成果物のみ.`05_TECH`(技術設計)・`06_TEST`(テスト)は実装フェーズで必要になった時点で作成し,立ち上げ時に空フォルダを作らない. + +## 方針決定 (Direction) + +プロジェクトの全体像を明確にする. + +- **人間が決めること**: プロジェクトの目的,対象ユーザー,スコープ(やること・やらないこと) +- **AI に依頼できること**: 要件の整理・構造化,類似プロジェクトの調査,要件定義書のドラフト作成 +- **成果物**: `PLAN_01_要件定義書.md` + +## 技術選定 (Tech Stack) + +要件に基づいて技術スタックを決定する. + +- **人間が決めること**: 最終的な技術選定の判断,チームのスキルセットとの適合性 +- **AI に依頼できること**: 要件に適した技術の候補提案,各候補のメリット・デメリット比較 +- **成果物**: `ENV_01_技術スタック.md` + +## 環境構築 (Environment Setup) + +開発環境を構築し,手順をドキュメント化する.初回のみの管理者作業と,メンバーが繰り返し行う構築手順を分けて整備する. + +- **前提条件**: 以下のツールは全プロジェクト共通で導入する. + - `git` — バージョン管理([GUIDE_04](GUIDE_04_Git運用ルール.md) で運用ルールを定義) + - `gh` — GitHub CLI(PR 作成・マージ等に使用) +- **基本方針**: 環境の再現性を重視し,手順書だけに頼らず構築を自動化・コード化できる方法を優先する(例: Docker,Dev Containers,Windows Sandbox,IaC ツール等). +- **人間が決めること**: 開発マシンの選定,クラウドサービスのアカウント作成,環境構築方法の選択 +- **AI に依頼できること**: 環境構築手順書の作成,設定ファイルの生成,`.gitignore` の作成,Dockerfile や devcontainer.json 等の構築用ファイルの作成 +- **成果物**: + - `ENV_02_環境構築手順.md` — メンバーの参加時や環境の再構築時に使う手順 + - `ENV_03_管理者用環境構築手順.md` — プロジェクト作成時に一度だけ行う初期設定(リポジトリ作成,外部サービスの設定等) + +## 仕様設計 (Specification) + +アプリケーションの設計を行う. + +- **人間が決めること**: ユーザー体験の方針,ビジネスロジックの最終判断 +- **AI に依頼できること**: アーキテクチャ設計のドラフト,データモデル定義,画面遷移図の整理 +- **成果物**: `SPEC_01_*.md`(プロジェクトの規模に応じて複数ファイルに分割) + +## 規約整備 (Coding Standards) + +技術スタックに応じたコーディング規約やプロジェクト固有のガイドを作成する. +汎用ガイド(GUIDE_01〜05)は本テンプレートに含まれている.ここではプロジェクト固有の規約を追加する. + +- **基本方針**: 言語・フレームワークの公式ガイドラインや広く採用されている標準規約に則る(例: Effective Dart,PEP 8,Google Style Guide 等).プロジェクト固有のルールは標準と異なる部分のみ定義する. +- **人間が決めること**: 標準規約でカバーされない判断(アーキテクチャパターンの選択等) +- **AI に依頼できること**: 標準規約を踏まえた規約のドラフト作成,参照元ガイドラインの調査 +- **作成すべきガイド**(推奨番号は GUIDE_03 に準拠): + - `GUIDE_06` コーディング規約 — 命名規則,フォーマット,import 順序,型の使い方,コメントの書き方,コード内ドキュメントの規則 + - `GUIDE_07` ディレクトリ構造規則 — プロジェクトのディレクトリ構成とファイル配置ルール + - `GUIDE_08` テスト方針 — テストの種類,粒度,実行タイミング,カバレッジ基準,モック方針,テストファイルの配置規則 + - `GUIDE_09` エラーハンドリング方針 — エラーの分類,処理方法,ログ出力の方針 + - ※ リファクタリング方針は言語に依存しないため,`.claude/agents/refactorer.md` の判断基準を共通ルールとして使用する + - ※ 機能実装完了フローは GUIDE_05 と `/implement` で定義済みのため,別途作成しない + +## 開発計画 (Development Plan) + +実装の順序とステップを決定する. + +- **人間が決めること**: 優先度,リリース計画,マイルストーン +- **AI に依頼できること**: 仕様を元にしたステップ分割の提案,依存関係の整理 +- **成果物**: `PLAN_02_開発ステップ.md` + +## 実装開始 (Implementation) + +開発計画に沿って AI と協働で実装を進める. + +- 各ステップの完了時に [GUIDE_02_ドキュメント作成ガイド](GUIDE_02_ドキュメント作成ガイド.md) と [GUIDE_04_Git運用ルール](GUIDE_04_Git運用ルール.md) に従ってコミット・PR を作成する. +- 仕様変更が発生した場合は,先にドキュメントを更新してから実装に反映する. + +## CLAUDE.md の管理 (CLAUDE.md Management) + +`CLAUDE.md` は AI が会話開始時に最初に読むファイルであり,プロジェクトの引継ぎ情報を一元管理する. +AI は毎回新しい会話で始まるため,このファイルが唯一の継続的な文脈となる. + +### 記載すべき内容 + +- **プロジェクト概要**: プロジェクト名,目的,技術スタックの要約 +- **開発進捗**: 現在のステップ(最新 1 行のみ).詳細な進捗履歴は `docs/PROGRESS.md` に追記する([GUIDE_05](GUIDE_05_エージェント運用ルール.md) の「進捗記録の運用ルール(CLAUDE.md / PROGRESS.md)」参照) +- **必須ルール**: AI が実装時に必ず守るべきルール(コーディング規約,コミット前チェック等の要点) +- **ドキュメント一覧**: docs/ 内のファイルへの参照パス + +### 更新タイミング + +- ステップの完了時に開発進捗を更新する(CLAUDE.md は最新 1 行に上書き,`docs/PROGRESS.md` は末尾に追記) +- ドキュメントの追加・削除・リネーム時に参照パスを更新する +- 必須ルールに変更があった場合に反映する + +### 運用上の注意 + +- CLAUDE.md は AI が毎回読み込むため,簡潔に保つ.詳細は docs/ のドキュメントに委ね,CLAUDE.md には要点と参照先のみ記載する. +- 進捗記録は二段構成(CLAUDE.md = 最新 1 行 / `docs/PROGRESS.md` = 追記型フルログ)で管理する.詳細は [GUIDE_05](GUIDE_05_エージェント運用ルール.md) を参照. +- プロジェクト固有のルールが増えたら,docs/ に独立ファイルとして切り出し,CLAUDE.md からはリンクで参照する. diff --git "a/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.md" "b/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.md" new file mode 100644 index 0000000..ed91906 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_02_\343\203\211\343\202\255\343\203\245\343\203\241\343\203\263\343\203\210\344\275\234\346\210\220\343\202\254\343\202\244\343\203\211.md" @@ -0,0 +1,114 @@ +# ドキュメント作成ガイドライン (Documentation Style Guide) + +本ガイドはプロジェクト内のマークダウンドキュメントの書式を統一するためのルールを定める. +基本方針として [Google Markdown Style Guide](https://google.github.io/styleguide/docguide/style.html) および [markdownlint](https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md) のルールに準拠し,本ガイドで上書きする項目のみ以下に記載する. + +## 基本フォーマット (Basic Format) + +- 文字コード: UTF-8 +- 改行コード: LF(推奨)または CRLF +- ファイル拡張子: `.md` +- ファイル末尾: 空行を 1 行入れて終了する(MD047) + +## 句読点・約物 (Punctuation) + +- 句読点: 「,」(全角カンマ)と「.」(全角ピリオド)を使用する. + - 「、」「。」は使用しない. +- コロン: 半角コロン+半角スペース「: 」を使用する. + - NG: 全角コロン「:」,スペースなし「:」 +- 括弧: 原則として半角 `( )` を使用する.強調や補足には全角 `( )` や `「 」` も許容する. +- 注釈: 補足には「※」(全角米印)+半角スペースを使用する. + - 例: ※ shared は client/server 両方から import して使用する. + +## 見出し (Headings) + +ATX スタイル(`#`)を使用する.Setext スタイル(`===` / `---` の下線)は使用しない. + +- `#` の後に半角スペースを 1 つ入れる(MD018) +- 見出しの前後に空行を 1 行入れる(MD022) +- 見出しレベルは飛ばさない(MD001) + - NG: `#` の直下に `###` +- ドキュメント内の `#`(H1)は 1 つだけにする(MD025) +- 見出しには番号を付けない.マークダウンの見出し構造で階層を表現する. +- 見出しの書式: `タイトル (English Title)` + - 例: `## 基本設計 (Basic Design)` + +### 見出しレベルの対応表 + +| レベル | 記法 | 用途 | +| --- | --- | --- | +| H1 | `#` | ドキュメントタイトル(ファイルに 1 つ) | +| H2 | `##` | 大見出し(セクション) | +| H3 | `###` | 中見出し(サブセクション) | +| H4 | `####` | 小見出し(トピック) | + +## リスト (Lists) + +- 箇条書きには `- `(半角ハイフン+半角スペース)を使用する(MD004) + - `*` `+` `・` は使用しない. +- ネストは 2 スペースでインデントする(MD007) +- 順序付きリストは `1.` の連番で記述する. +- リストの前後に空行を 1 行入れる(MD032) + +## 強調 (Emphasis) + +- 太字: `**テキスト**` を使用する.`__テキスト__` は使用しない(MD050) +- 斜体: `*テキスト*` を使用する.`_テキスト_` は使用しない(MD049) +- 太字斜体: `***テキスト***` を使用する. + +## コードブロック・インラインコード (Code) + +- コードブロックにはフェンス(` ``` `)を使用し,言語名を明記する(MD040) + + ````markdown + ```dart + final name = 'DxNavi'; + ``` + ```` + +- インラインコードにはバッククォート `` ` `` を使用する. + - 例: `build_runner` コマンドを実行する. +- コマンド例にはシェル言語を指定する. + + ````markdown + ```bash + dart run build_runner build --delete-conflicting-outputs + ``` + ```` + +## リンク・画像 (Links & Images) + +- リンク: `[テキスト](URL)` 形式を使用する. +- 画像: `![代替テキスト](パス)` 形式を使用し,代替テキストを必ず記述する(MD045) +- プロジェクト内リンクは相対パスを使用する. + +## テーブル (Tables) + +- ヘッダー行とセパレータ行を必ず含める. +- セル内は簡潔に記述し,長い場合はリンクや脚注で補足する. + +```markdown +| 項目 | 説明 | +| --- | --- | +| 名前 | 値 | +``` + +## 空行・余白 (Spacing) + +- 連続する空行は最大 1 行までとする(MD012) +- 見出し・リスト・コードブロックの前後に空行を 1 行入れる(MD022, MD031, MD032) +- 行末の不要な空白は削除する(MD009) + +## その他 (Miscellaneous) + +- HTML タグは原則使用しない.マークダウン記法で表現できない場合のみ許容する. +- 1 行の長さに厳密な上限は設けないが,可読性のために適度に改行する. +- ディレクトリ構造の表現にはコードブロック内でツリー記号(`├──`,`│`,`└──`)を使用する. + +```text +project/ +├── lib/ +│ ├── core/ +│ └── features/ +└── test/ +``` diff --git "a/docs/01_GUIDE/GUIDE_03_\343\203\225\343\202\241\343\202\244\343\203\253\345\221\275\345\220\215\350\246\217\345\211\207.md" "b/docs/01_GUIDE/GUIDE_03_\343\203\225\343\202\241\343\202\244\343\203\253\345\221\275\345\220\215\350\246\217\345\211\207.md" new file mode 100644 index 0000000..f9d43d2 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_03_\343\203\225\343\202\241\343\202\244\343\203\253\345\221\275\345\220\215\350\246\217\345\211\207.md" @@ -0,0 +1,31 @@ +# ドキュメント管理・ファイル命名規則 (File Naming Conventions) + +## 命名の基本方針 (Basic Policy) + +プロジェクトの規模拡大に伴うファイルの散乱を防ぎ,開発メンバーおよび AI がファイルの内容・文脈を即座に特定できるようにするため,以下の規則を適用する. + +### 基本フォーマット + +`[カテゴリ]_[連番]_[ファイル名].md` + +- 区切り文字: アンダースコア `_` を使用する. +- 連番: 01 から始まる 2 桁の数字とする. +- 拡張子: マークダウン `.md` とする. + +## カテゴリ定義 (Category Definitions) + +ファイル名の先頭に付与するプレフィックス(接頭辞)定義. + +| カテゴリ | ディレクトリ | 内容 | 対象例 | +| --- | --- | --- | --- | +| `GUIDE_` | `01_GUIDE/` | ルール,規約,運用フロー | スタイルガイド,命名規則,Git 運用ルール | +| `ENV_` | `02_ENV/` | 開発環境,プロジェクトの土台 | 環境構築手順,技術スタック一覧,パッケージ構成図 | +| `PLAN_` | `03_PLAN/` | 進行計画,スケジュール,要件定義 | WBS,ロードマップ,要件定義書,タスク一覧 | +| `SPEC_` | `04_SPEC/` | ユーザーから見える仕様 | 企画書,画面遷移図,パラメータ設定 | +| `TECH_` | `05_TECH/` | エンジニア向けの技術設計 | 通信プロトコル仕様,データベース設計,クラス設計 | +| `TEST_` | `06_TEST/` | テスト計画,品質保証 | 単体テスト仕様書,シナリオテスト計画,品質基準 | + +## 運用ルール (Operational Rules) + +- 1 ファイル 1 テーマ: ファイルサイズが肥大化しすぎないよう,トピックごとにファイルを分割することを推奨する.これにより,AI へのコンテキスト入力精度が向上する. +- スタイルの継承: 新規作成するファイルも,必ず [GUIDE_02_ドキュメント作成ガイド](GUIDE_02_ドキュメント作成ガイド.md) に記載された書式に従うこと. diff --git "a/docs/01_GUIDE/GUIDE_04_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" "b/docs/01_GUIDE/GUIDE_04_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" new file mode 100644 index 0000000..3b79351 --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_04_Git\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" @@ -0,0 +1,181 @@ +# Git 運用ルール (Git Operation Rules) + +## 基本方針 (Basic Policy) + +チーム開発におけるコードの整合性を保ち,手戻りを防ぐために以下の運用フローを徹底する. + +- **メインブランチ (main)**: + - 本番環境または常に動作可能な状態を維持するブランチ. + - 直接のコミット(直プッシュ)は禁止する.必ずプルリクエスト(PR)経由でマージする. +- **作業ブランチ (Feature Branch)**: + - 機能追加やバグ修正ごとに `main` から派生させて作成する. + - 作業完了後,`main` へマージし,原則として削除する. +- **`.gitignore`**: + - リポジトリ作成時に必ず整備する. + - ビルド成果物,依存パッケージ(`node_modules/` 等),環境変数ファイル(`.env` 等)は必ず除外する. + - `git add .` を安全に使うための前提条件であるため,メンバー追加時にも確認する. + +## ブランチ命名規則 (Branch Naming) + +### プレフィックス (Prefix) + +作業の種類を一目で判別するために,以下のプレフィックスを使用する. + +| プレフィックス | 用途 | +| --- | --- | +| `feature/` | 新機能の実装,仕様変更 | +| `fix/` | バグ修正 | +| `refactor/` | コードの整理(挙動は変えない) | +| `docs/` | ドキュメントの追記・修正 | +| `chore/` | ビルド設定やツール導入など,雑多な作業 | + +### 書式 (Format) + +- 書式: `[プレフィックス][概要]` +- 区切り: スラッシュ `/` を使用する.概要内の単語区切りはハイフン `-` を使用する. +- 概要: 作業内容を端的に表す英単語 2〜4 語程度(小文字)とする. +- 例: + - `feature/player-jump` + - `fix/collision-bug` + - `docs/guide-update` + +## 開発フロー (Development Workflow) + +作業を開始してからマージされるまでの手順. + +### ローカルの最新化 + +作業開始前は必ず `main` ブランチに切り替え,リモートの最新状態を取り込む. + +```bash +git checkout main +git pull origin main +``` + +### 作業ブランチの作成 + +最新の `main` から新しいブランチを作成して移動する. + +```bash +git checkout -b feature/new-function +``` + +### 実装とコミット + +- 作業単位(意味のあるまとまり)ごとにコミットする. +- 巨大なコミットは避け,レビューしやすい粒度を心がける. +- AI によるコミットメッセージの生成機能を利用してもよい.ただし,生成されたメッセージは必ず「コミットメッセージ」セクションの書式ルールに合わせて修正すること. + +```bash +git add . +git commit -m "[add] 新機能を実装" +``` + +### リモートへのプッシュ + +作業ブランチをリモートリポジトリへ送信する. + +```bash +git push origin feature/new-function +``` + +### プルリクエスト (PR) の作成 + +GitHub CLI (`gh`) を使用して PR を作成する. + +```bash +gh pr create --title "[add] 新機能を実装" --body "概要" +``` + +- `--title` はコミットメッセージと同じ書式(`[タグ] 内容`)とする. +- 必要に応じて `--reviewer` でレビュワーを指定する. + +### レビューと修正の対応 + +- レビュワーのコメントを確認し,修正が必要な場合はローカルで修正・コミット・プッシュを繰り返す. +- 全ての指摘に対応し,レビュワーから Approve をもらう. + +### マージの実行 + +- マージ方式は「Create a merge commit」を使用する(作業ブランチの全コミット履歴が `main` に残る). + - 「Squash and merge」「Rebase and merge」は使用しない. + +```bash +gh pr merge --merge --delete-branch +``` + +### ローカル環境のクリーンアップ + +マージ完了後はローカル環境も最新状態に戻し,古いブランチを削除する. + +```bash +git checkout main +git pull origin main +git branch -d feature/new-function +``` + +## コミットメッセージ (Commit Messages) + +### 書式 + +- 書式: `[タグ] 内容` +- 言語: 日本語 +- 句読点: 末尾に句点は不要 + +### タグ一覧 + +| タグ | 用途 | +| --- | --- | +| `[add]` | ファイルや機能の追加 | +| `[update]` | 機能やデータの更新・修正 | +| `[fix]` | バグ修正 | +| `[remove]` | 削除 | +| `[clean]` | 整理,リファクタリング | + +## トラブルシューティング (Troubleshooting) + +### コンフリクトが発生した場合 + +他メンバーの変更と競合した場合の対処手順. + +**main の取り込み** + +作業ブランチに `main` の最新内容をリベースして競合箇所を洗い出す.`merge` ではなく `rebase` を使うことで,履歴が線形に保たれレビューしやすくなる. + +```bash +git checkout main +git pull origin main +git checkout feature/new-function +git rebase main +``` + +**競合の解消** + +エディタ上で `<<<<<<<`,`=======`,`>>>>>>>` で囲まれた箇所を手動で修正する.修正後,以下のコマンドでリベースを続行する. + +```bash +git add [修正したファイル] +git rebase --continue +``` + +全ての競合が解消されたらプッシュする.リベース後は履歴が書き換わるため `-f` オプションが必要になる. + +```bash +git push -f origin feature/new-function +``` + +### 間違えて main にコミットしてしまった場合 + +**まだプッシュしていない場合** + +コミットを取り消し,変更内容を保持したまま新しいブランチへ移動する. + +```bash +git reset --soft HEAD^ +git checkout -b feature/new-function +git commit -m "[add] ..." +``` + +**すでにプッシュしてしまった場合** + +`main` への force push はチーム全員の履歴を壊す危険があるため,自分では対処しない.直ちにチームメンバーに報告し,全員で対応方針を決める. diff --git "a/docs/01_GUIDE/GUIDE_05_\343\202\250\343\203\274\343\202\270\343\202\247\343\203\263\343\203\210\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" "b/docs/01_GUIDE/GUIDE_05_\343\202\250\343\203\274\343\202\270\343\202\247\343\203\263\343\203\210\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" new file mode 100644 index 0000000..2936c2a --- /dev/null +++ "b/docs/01_GUIDE/GUIDE_05_\343\202\250\343\203\274\343\202\270\343\202\247\343\203\263\343\203\210\351\201\213\347\224\250\343\203\253\343\203\274\343\203\253.md" @@ -0,0 +1,192 @@ +# エージェント運用ルール (Agent Operation Rules) + +実装品質を担保するために,3 つの専門エージェントを用いた開発パイプラインを定義する. + +## 基本方針 (Basic Policy) + +- 「実装完了」とは,コーディング・テスト・リファクタリングの全フェーズが完了した状態を指す. +- 各フェーズは専門エージェントが担当し,フレッシュなコンテキストでレビューする. +- フェーズのスキップは原則禁止する.リファクタリング不要の判断は Refactorer エージェント自身が行う. +- 各フェーズ間で人間が確認・判断を行う. + +## エージェント一覧 (Agent List) + +| エージェント | 役割 | フェーズ | +| --- | --- | --- | +| `coder` | 機能実装・バグ修正 | Phase 1 | +| `tester` | 仕様ベースのテスト作成・実行 | Phase 2 | +| `refactorer` | コード品質の改善 | Phase 3 | + +## 実装パイプライン (Implementation Pipeline) + +### 開始方法 + +```bash +/implement <タスク内容> +``` + +### 全体フロー + +``` +人間: /implement <タスク内容> + │ + ├─ ブランチ作成(GUIDE_04 準拠) + │ + ├─ Phase 1 ──▶ [Coder] + │ 実装に集中.テスト・リファクタは行わない + │ + ├─ 人間の確認ポイント 1 + │ ブラウザ/実機で動作確認 + │ OK → 続行 / NG → フィードバックして修正 + │ + ├─ Phase 2 ──▶ [Tester] + │ 仕様ベースでテスト作成・実行 + │ + ├─ Phase 2 完了後の分岐 + │ 全テスト成功 → 自動で Phase 3 へ + │ テスト失敗 → 人間に報告し判断を仰ぐ + │ + ├─ Phase 3 ──▶ [Refactorer] + │ テストを安全網としてリファクタリング + │ テスト再実行で挙動が変わっていないことを保証 + │ + ├─ Phase 4 ──▶ ドキュメント更新 + │ docs/, CLAUDE.md, docs/PROGRESS.md を必要に応じて更新 + │ 更新がある場合のみ人間の確認を挟む + │ 結果を .claude/commit-context.md に書き出す + │ + └─ 完了 → /commit でコミット +``` + +### Phase 1: コーディング (Coding) + +- Coder エージェントが `docs/` を読んで実装する. +- 実装完了後,実装サマリーを出力する. +- テストやリファクタリングは行わない. +- コミットはしない. + +### 人間の確認ポイント 1 + +- ブラウザ・実機での動作確認(AI にはできない確認). +- 問題があればフィードバックし,Coder に修正を指示する. + +### Phase 2: テスト (Testing) + +- Tester エージェントが仕様(`docs/04_SPEC/`)を基準にテストを作成する. +- テストは実装コードではなく**仕様**を基準に書く. +- 実装が仕様と異なればテストが失敗し,バグを検出する. + +### Phase 2 完了後の分岐 + +- **全テスト成功**: テストサマリーを表示し,自動的に Phase 3 に進む. +- **テスト失敗あり**: 人間に報告し,判断を仰ぐ. + - 仕様の問題 → 仕様を修正 + - 実装の問題 → Coder に修正を委譲 + - テストの問題 → Tester に修正を委譲 + +### Phase 3: リファクタリング (Refactoring) + +- Refactorer エージェントがテストを安全網としてコード品質を改善する. +- 挙動は変更しない. +- リファクタリング後にテストを再実行し,全テストが通ることを確認する. +- リファクタリング不要と判断した場合は,理由を明示して終了する. + +### Phase 4: ドキュメント更新 (Documentation) + +Phase 3 完了後,実装内容に応じて `docs/`, `CLAUDE.md`, `docs/PROGRESS.md` を更新する. + +- **チェック観点**: + - API・データ構造の変更 → `docs/04_SPEC/` の該当仕様を更新 + - 環境・依存関係の変更 → `docs/02_ENV/` を更新 + - 開発ステップの進捗 → `docs/03_PLAN/` や進捗記録(`CLAUDE.md` の進捗欄+ `docs/PROGRESS.md`)を更新(書式は本ガイドの「進捗記録の運用ルール(CLAUDE.md / PROGRESS.md)」に従う.`git log` で取れる詳細は書かない) + - 規約・運用ルールの変更 → `docs/01_GUIDE/` を更新 +- **該当なし**: ドキュメント更新が不要な変更(軽微なバグ修正,リファクタリングのみ等)はスキップ可. +- **更新がある場合のみ**人間の確認を挟む.更新不要の場合は確認なしで完了処理に進む. +- **コミットコンテキストの書き出し**: Phase 4 の結果(更新の有無と理由)を `.claude/commit-context.md` に書き出す.このファイルは `/commit` が参照し,`docs/`, `CLAUDE.md`, `docs/PROGRESS.md` の更新漏れチェックをスキップするために使う(`.gitignore` 対象). + +### 完了処理 + +- `/implement` はコミットを行わない.完了後は `/commit` でコミットする. +- `/commit` は `.claude/commit-context.md` が存在する場合,`docs/`, `CLAUDE.md`, `docs/PROGRESS.md` の更新漏れチェックをスキップする.存在しない場合(`/implement` を経由していない場合)は警告のみ行う. + +## コンテキスト受け渡し (Context Passing) + +各エージェントは前フェーズのサマリーを入力として受け取る.加えて `git diff` で実際の変更差分を自ら確認する. + +| フェーズ | 受け取る情報 | +| --- | --- | +| Coder | タスク内容 | +| Tester | Coder の実装サマリー + git diff | +| Refactorer | Coder + Tester のサマリー + git diff | + +## 人間の役割 (Human's Role) + +| タイミング | 人間がやること | +| --- | --- | +| 開始時 | タスクの指示(`/implement <何をするか>`) | +| Phase 1 後 | 動作確認(ブラウザ・実機など AI にできない確認) | +| Phase 2 後 | テスト失敗時のみ方針判断(全成功なら自動で Phase 3 へ) | +| Phase 4 後 | ドキュメント更新がある場合のみ確認 → `/commit` でコミット | + +人間の本質的な役割は「AI にできない判断と確認」であり,各フェーズの品質のゲートキーパーとなる. + +## コミットルール (Commit Rules) + +パイプライン完了後は `/commit` でコミットする.コミットメッセージのタグ等は [GUIDE_04](GUIDE_04_Git運用ルール.md) に従う. + +※ リファクタリングとテストは実装と一体の成果物として,まとめてコミットする.必要に応じて分割コミットも可. + +## 進捗記録の運用ルール(CLAUDE.md / PROGRESS.md) + +進捗記録は **2 ファイルの二段構成**で管理する.Phase 4 や `/setup` 中断時にこれらを更新する. + +| ファイル | 役割 | 更新方法 | +| --- | --- | --- | +| `CLAUDE.md` の「開発進捗」セクション | **最新ステップ 1 行のみ**(毎ターン読み込まれる薄い目印) | 上書き | +| `docs/PROGRESS.md` | **追記型のフル進捗ログ**(動機・設計判断・失敗パターン含む) | 末尾に追記 | + +**背景**: CLAUDE.md は毎ターン読み込まれるため,追記型運用にするとコンテキスト圧迫の原因になる.一方で進捗の経緯・失敗パターン・設計判断はタスクを跨いで価値があるため捨てたくない.そこで「常に読まれる薄いポインタ(CLAUDE.md)」と「必要な時だけ読む厚いログ(PROGRESS.md)」に分離する.関数名・引数・テスト件数等の実装詳細は `git log` とコミットメッセージに完全な形で残るため,どちらにも書かない. + +### CLAUDE.md「開発進捗」の書き方 + +- **最新 1 行のみ**.古い行は上書きで消す(履歴は PROGRESS.md に残るので消えてよい) +- 基本形式: `最新: <ステップ見出し>` +- 関数名・テスト件数・実装手順詳細は書かない(PROGRESS.md と `git log` に任せる) + +### docs/PROGRESS.md の書き方 + +`docs/PROGRESS.md` は追記型.最新エントリを**末尾に追記**する(時系列順.古いものが上,新しいものが下). + +**書く(PROGRESS.md に残す価値が高いもの)**: + +以下は PROGRESS.md に置く価値があるが,全て書く必要はない.シンプルなステップなら状況の 1 行だけで十分.書くことが少ない時に無理に伸ばさない. + +- 状況: 何が完了したか(1 行) +- 動機・原因: なぜそれをやったか(既存の問題点・要件変更・前バージョンの欠点など) +- 重要な設計判断: 他案との比較が必要な場合のみ.「A 案ではなく B 案を選んだ理由」が将来の判断材料になるとき +- 失敗パターンの圧縮サマリ: 「① X 案 → Y で破綻 / ② Z 案で解決」のような 1〜2 行.同じ轍を踏まないための知識として残す.試行錯誤を時系列で全部書かず,本質的に異なるアプローチの失敗だけを並列項目として記録する +- 未実装・後段: 「次に何をすべきか」を思い出すための短いメモ + +**書かない(コミットメッセージと `git log` に任せる)**: + +以下は `git log ` または `git show ` で完全な情報が取れる.PROGRESS.md に書くと重複・陳腐化する. + +- 関数名・引数・型シグネチャ +- テスト件数の内訳(合計件数のみなら可だが数字は陳腐化するので省略推奨) +- リファクタリングの手順詳細 +- 撤去・新規追加の関数リスト +- 具体的な定数値・閾値(設計判断の核心に関わるものを除く) +- 数値範囲の細部(実装パラメータ等) +- 後方互換性の細かい仕様 +- 「全テスト N passed」の報告(pass している前提のため不要) + +**長さと書式**: + +- 1 エントリの長さは内容次第で可変.書くことが少なければ **1 行で十分**.複数系統の作業を 1 ステップにまとめた等で必要なら長くなってもよい.無理に伸ばさず無理に削らず,「未来の自分(または他人)が辿れるか」だけを基準にする +- 基本形式: `- [x] **<簡潔な見出し>**: <1〜2 文の要約>`.必要に応じて下に動機・設計判断・失敗パターンを 1〜2 行ずつ追加 +- 太字は**見出しに使う**(目次の項目として目立たせる).本文中で多用しない +- 長い箇条書きを避ける.箇条書きは「失敗パターン ① ② ③」のような本質的に異なる選択肢の並列項目に限定する + +**既存エントリの長文化に気付いたとき**: + +過去のエントリで「詳細をベタ書きしていて目次として機能しなくなっている」ものを見つけたら,ユーザーに圧縮を提案する.自動で削らない(背景情報の価値判断はユーザーが行う).提案時は「この情報は `git log` にあるので削れる / これは失敗パターンなので残すべき」のように切り分けて示すこと. diff --git "a/docs/02_ENV/ENV_01_\351\226\213\347\231\272\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.md" "b/docs/02_ENV/ENV_01_\351\226\213\347\231\272\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.md" new file mode 100644 index 0000000..975f2fe --- /dev/null +++ "b/docs/02_ENV/ENV_01_\351\226\213\347\231\272\347\222\260\345\242\203\346\247\213\347\257\211\346\211\213\351\240\206.md" @@ -0,0 +1,114 @@ +# 開発環境構築手順 (Development Environment Setup) + +## セットアップ方法の選択 (Setup Method) + +### 自動セットアップ(推奨) + +リポジトリルートの `setup.ps1` を使用することで,Visual Studio のインストール,データフォルダの作成,NuGet パッケージの復元を自動化できる. + +**実行手順** + +1. PowerShell を管理者権限で開く. +2. リポジトリのルートに移動する. + + ```powershell + cd [リポジトリのパス] + ``` + +3. スクリプトの実行ポリシーを一時的に変更する. + + ```powershell + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + ``` + +4. セットアップスクリプトを実行する. + + ```powershell + .\setup.ps1 + ``` + +5. スクリプト完了後,IC Imaging Control SDK を手動でインストールする. + - 詳細は「必要なソフトウェア — IC Imaging Control SDK」を参照する. + +**自動化される内容** + +- Visual Studio 2022 のインストール(未インストール時のみ) + - `.vsconfig` により「.NET デスクトップ開発」ワークロードが自動で設定される. +- `C:\TIAS_Data` フォルダの作成(未作成時のみ) +- NuGet パッケージの復元 + +**自動化されない内容(手動対応が必要)** + +- IC Imaging Control SDK のインストール +- 実行時設定ファイルの配置(config.xml,カメラ設定 XML,CSV) + +### 手動セットアップ + +スクリプトを使用しない場合は,以下の「必要なソフトウェア」〜「実行時の準備」の手順に従って手動で構築する. + +## 必要なソフトウェア (Required Software) + +### Visual Studio 2022 + +- 公式サイトからインストーラをダウンロードしてインストールする. +- ワークロード選択で「.NET デスクトップ開発」を有効にする. +- リポジトリルートの `.vsconfig` をインストーラで読み込むと,必要なワークロードが自動で提案される. + +### IC Imaging Control SDK + +- The Imaging Source が提供するカメラ制御ライブラリ. +- ImagingSource 製カメラ(DFK33UX178,DFK23UX249)の使用に必要. +- インストール後,参照 DLL が Visual Studio から認識されることを確認する. + +### Lumenera SDK + +- Lumenera 製カメラ(Lw110)の使用に必要. +- `lumenera.api.dll` はリポジトリ内に同梱されている. + +## リポジトリのセットアップ (Repository Setup) + +1. リポジトリのクローン + + ```bash + git clone [リポジトリURL] + cd TIASshot + ``` + +2. ソリューションを開く + - `TIASshot.sln` を Visual Studio 2022 で開く. + +3. NuGet パッケージの復元 + - Visual Studio のメニューから「ビルド」→「NuGet パッケージの復元」を実行する. + - または,パッケージマネージャーコンソールで以下を実行する. + + ```bash + nuget restore TIASshot.sln + ``` + +4. ビルド + - 「ビルド」→「ソリューションのビルド」を実行し,エラーがないことを確認する. + +## 実行時の準備 (Runtime Preparation) + +### 設定ファイルの配置 + +- `TIASshot/config.xml` が実行ファイルと同じディレクトリに存在することを確認する. +- パラメータの詳細は `SPEC_02_設定ファイル仕様.md` を参照する. + +### カメラ設定ファイルの確認 + +- ImagingSource カメラを使用する場合,以下のファイルが同ディレクトリに必要. + - `DFK33UX178.xml` + - `DFK23UX249.xml` + +### TCC参照ファイルの確認 + +- 以下の CSV ファイルが実行ファイルと同じディレクトリに必要. + - `tcc_srgb.csv`: sRGB 変換の参照値 + - `tcc_xyz.csv`: XYZ 変換の参照値 + +### データ保存フォルダの確認 + +- `config.xml` の `` に指定したフォルダへの書き込み権限があることを確認する. +- デフォルトは `C:\TIAS_Data`. +- `setup.ps1` を実行した場合,このフォルダは自動で作成される. diff --git "a/docs/02_ENV/ENV_02_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.md" "b/docs/02_ENV/ENV_02_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.md" new file mode 100644 index 0000000..98dfbbb --- /dev/null +++ "b/docs/02_ENV/ENV_02_\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\346\247\213\346\210\220.md" @@ -0,0 +1,72 @@ +# ディレクトリ構成 (Directory Structure) + +## 全体構成 (Overview) + +```text +TIASshot/ +├── CLAUDE.md ← AI向けガイドライン(ドキュメント・コーディング規則の参照) +├── README.md ← プロジェクト概要 +├── TIASshot.sln ← Visual Studio ソリューションファイル +├── TIASshot/ ← メインプロジェクト +└── docs/ ← ドキュメント +``` + +## メインプロジェクト TIASshot/ (Main Project) + +### ソースコード + +```text +├── Program.cs ← エントリポイント +├── Form1.cs ← メインフォーム(UI・操作イベント) +├── Form1.Designer.cs ← メインフォームのデザイナー自動生成コード +├── PreviewMonitor.cs ← プレビューモニタフォーム +├── PreviewMonitor.Designer.cs ← プレビューモニタのデザイナー自動生成コード +├── CameraBase.cs ← カメラ制御の基底クラス(共通処理) +├── IScam.cs ← ImagingSource カメラの実装 +├── Lucam.cs ← Lumenera カメラの実装 +├── Config.cs ← config.xml の読み込みユーティリティ +└── LightSource.cs ← 光源(シリアル通信)制御 +``` + +### 設定・データファイル + +```text +├── config.xml ← アプリケーション設定(パラメータ定義) +├── DFK33UX178.xml ← ImagingSource DFK33UX178 カメラ設定 +├── DFK23UX249.xml ← ImagingSource DFK23UX249 カメラ設定 +├── tcc_srgb.csv ← TCC sRGB 変換参照値(24色票×3ch) +└── tcc_xyz.csv ← TCC XYZ 変換参照値(24色票×3ch) +``` + +### 外部ライブラリ・リソース + +```text +├── lumenera.api.dll ← Lumenera SDK(同梱) +├── lumenera.api.xml ← Lumenera SDK ドキュメント +├── CalibDone.wav ← キャリブレーション完了音 +├── OneShot.wav ← 1枚撮影完了音 +├── MultiShot.wav ← 連続撮影完了音 +└── main.ico ← アプリケーションアイコン +``` + +### プロジェクト設定 + +```text +├── TIASshot.csproj ← プロジェクトファイル +├── App.config ← .NET アプリケーション設定 +├── packages.config ← NuGet パッケージ一覧 +└── Properties/ + ├── AssemblyInfo.cs ← アセンブリ情報 + ├── Resources.Designer.cs ← リソース自動生成コード + └── Settings.Designer.cs ← アプリ設定自動生成コード +``` + +## ドキュメント docs/ (Documents) + +```text +docs/ +├── 01_GUIDE/ ← チームルール・規約(命名,Git,コーディング,コメント) +├── 02_ENV/ ← 開発環境・構成に関するドキュメント(本ディレクトリ) +├── 03_SPEC/ ← 機能仕様・設定パラメータ定義 +└── 04_TECH/ ← クラス設計・アルゴリズム等の技術設計 +``` diff --git "a/docs/02_ENV/ENV_03_\344\276\235\345\255\230\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\344\270\200\350\246\247.md" "b/docs/02_ENV/ENV_03_\344\276\235\345\255\230\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\344\270\200\350\246\247.md" new file mode 100644 index 0000000..3ef2eac --- /dev/null +++ "b/docs/02_ENV/ENV_03_\344\276\235\345\255\230\343\203\251\343\202\244\343\203\226\343\203\251\343\203\252\344\270\200\350\246\247.md" @@ -0,0 +1,41 @@ +# 依存ライブラリ一覧 (Dependency List) + +## 開発環境 (Development Environment) + +- IDE: Visual Studio 2022 +- ターゲットフレームワーク: .NET Framework 4.8 + +## NuGet パッケージ (NuGet Packages) + +`packages.config` で管理する.Visual Studio のパッケージ復元で自動取得される. + +**OpenCvSharp4 関連** + +- `OpenCvSharp4` (4.10.0): OpenCV の C# ラッパー本体 +- `OpenCvSharp4.Extensions` (4.10.0): Bitmap 変換等の拡張機能 +- `OpenCvSharp4.runtime.win` (4.10.0): Windows 向けネイティブランタイム +- `OpenCvSharp4.Windows` (4.10.0): Windows Forms 向け統合パッケージ +- `OpenCvSharp4.WpfExtensions` (4.10.0): WPF 向け拡張機能 + +**.NET 補完ライブラリ** + +- `System.Buffers` (4.5.1) +- `System.Drawing.Common` (8.0.0) +- `System.Memory` (4.5.5) +- `System.Numerics.Vectors` (4.5.0) +- `System.Runtime.CompilerServices.Unsafe` (6.0.0) +- `System.ValueTuple` (4.5.0) + +## 外部 SDK(別途インストールが必要) (External SDKs) + +**IC Imaging Control SDK (The Imaging Source)** + +- 用途: ImagingSource 製カメラの制御(DFK33UX178,DFK23UX249) +- 名前空間: `TIS.Imaging` +- インストール: The Imaging Source の公式サイトから取得する + +**Lumenera SDK** + +- 用途: Lumenera 製カメラの制御(Lw110) +- DLL: `lumenera.api.dll`(リポジトリ内に同梱) +- 別途インストール不要(同梱 DLL を参照) diff --git "a/docs/03_SPEC/SPEC_01_\346\251\237\350\203\275\344\273\225\346\247\230.md" "b/docs/03_SPEC/SPEC_01_\346\251\237\350\203\275\344\273\225\346\247\230.md" new file mode 100644 index 0000000..7feab10 --- /dev/null +++ "b/docs/03_SPEC/SPEC_01_\346\251\237\350\203\275\344\273\225\346\247\230.md" @@ -0,0 +1,96 @@ +# 機能仕様 (Feature Specification) + +## 対応カメラ (Supported Cameras) + +起動時に Lucam → ImagingSource の順で接続を試みる. + +**ImagingSource カメラ(新カメラ)** + +- 対応機種: DFK33UX178,DFK23UX249 + - ※ README には DBK33UX178 と記載されていたが,ソースコード上は DFK33UX178 として扱われている.実機の型番は要確認. +- SDK: IC Imaging Control (TIS.Imaging) +- 設定ファイル: `[デバイス名].xml`(例: `DFK33UX178.xml`) + +**Lumenera カメラ(旧カメラ)** + +- 対応機種: Lw110 +- SDK: Lumenera SDK(`lumenera.api.dll`) + +## プレビュー (Preview) + +- 起動後,接続したカメラのライブ映像をメインウィンドウに表示する. +- サブモニタへのプレビュー表示にも対応する(PreviewMonitor). +- ImagingSource カメラはプレビュー時に ROI クリップを適用する. + +## 自動キャリブレーション (Auto Calibration) + +プレビュー中に舌診チャートを検出すると自動でキャリブレーションを開始する. + +### チャート検出 + +- ArUco マーカー(ID 40, 41)を使用してチャートを自動検出する. +- チャートが一定フレーム数静止したことを確認してからキャリブを開始する. + +### ホワイトバランス調整 + +- チャートの白色票(24色票の13番)を基準にカメラのゲインを自動調整する. +- 目標値は `config.xml` の `Calib/Reference` で指定する. + +### TCC(色変換行列)計算 + +- 24パッチの平均 RGB 値を計測し,最小二乗法(SVD)で変換行列を算出する. +- 変換次元数(多項式の次数)は `Calib/ConversionChannels` で指定する. + - 4: 1次式(R,G,B,1) + - 10: 2次式(+RG,RB,GB,R²,G²,B²) + - 17: 3次式(+R²B,R²G,G²R,G²B,B²R,B²G,RGB) +- 複数の次元数をカンマ区切りで同時に指定可能(例: `4,10,17`). +- 算出した変換行列は CSV ファイルに保存される. + +## 撮影 (Shooting) + +キャリブレーション完了後に撮影ボタンが有効になる. + +**1枚撮影** + +- 撮影した画像を1枚保存する. + +**連続撮影** + +- 指定した枚数・間隔で連続撮影する. +- 枚数・間隔は UI で変更可能(デフォルト値は `config.xml` で設定). + +**保存される画像** + +- 元画像(RGB): `Shot{NO}.png` +- sRGB 変換画像: `sRGB{CN}_{NO}.jpg`(指定した次元数ぶん生成される) + +## データ保存 (Data Saving) + +撮影・キャリブレーション結果は保存フォルダ以下に日時フォルダで自動保存される. + +**保存先フォルダ構成** + +- `[SaveFolder]/[日付]/[時刻]-[データ名]/` + +**キャリブレーション保存ファイル** + +- `TCC.png`: キャリブ時の画像 +- `TCC_ROIs.jpg`: チャートの ROI 確認画像 +- `TCC_RGB.csv`: チャート24色票の RGB 値 +- `TCC_sRGB{CN}.csv`: チャート24色票の sRGB 変換値 +- `Conv_RGB-sRGB{CN}.csv`: RGB→sRGB 変換行列 +- `Conv_RGB-XYZ{CN}.csv`: RGB→XYZ 変換行列 +- `Conv_sRGB-XYZ{CN}.csv`: sRGB→XYZ 変換行列 + +**撮影保存ファイル** + +- `Info.csv`: 撮影情報(カメラ型番・SN,露光時間,ゲイン等) +- `Shot{NO}.png`: 元画像(RGB) +- `sRGB{CN}_{NO}.jpg`: sRGB 変換画像 + +## 光源制御 (Light Source Control) + +- シリアル通信(USB-シリアル変換)で光源の ON/OFF を制御する. +- 対応デバイス: Silicon Labs CP210x(`config.xml` で変更可能). +- キャリブレーション中は光源の切り替えが無効になる. +- 光源デバイスが見つからない場合,光源ボタンが無効化される. diff --git "a/docs/03_SPEC/SPEC_02_\350\250\255\345\256\232\343\203\225\343\202\241\343\202\244\343\203\253\344\273\225\346\247\230.md" "b/docs/03_SPEC/SPEC_02_\350\250\255\345\256\232\343\203\225\343\202\241\343\202\244\343\203\253\344\273\225\346\247\230.md" new file mode 100644 index 0000000..24a3266 --- /dev/null +++ "b/docs/03_SPEC/SPEC_02_\350\250\255\345\256\232\343\203\225\343\202\241\343\202\244\343\203\253\344\273\225\346\247\230.md" @@ -0,0 +1,129 @@ +# 設定ファイル仕様 (Configuration File Specification) + +実行ファイルと同じディレクトリに `config.xml` を配置する. +XML のルート要素は `` とする. + +※ ファイル名・保存先のテンプレート変数: `{NO}` は4桁連番,`{CN}` は2桁の次元数に展開される. + +## Lucam カメラ設定 (Lucam Camera) + +Lumenera Lw110 の初期パラメータ. + +**``** + +- ``: 露光時間 (ms) + - 例: `60.0` +- ``: マスターゲイン + - 例: `1.5` +- ``: ブルーゲイン + - 例: `2.62` +- ``: グリーンゲイン + - 例: `1.72` +- ``: レッドゲイン + - 例: `1.70` + +## ImagingSource カメラ設定 (ImagingSource Camera) + +各カメラの ROI(関心領域)設定.カメラ名はデバイス名と一致させる. + +**`` / ``** + +- `` + - ``: ROI の左端座標 (px) + - ``: ROI の上端座標 (px) + - ``: ROI の幅 (px) + - ``: ROI の高さ (px) + +※ ImagingSource カメラは画像を転置してから ROI を切り出す.X・Y・W・H は転置後の座標系で指定する. + +## キャリブレーション設定 (Calibration) + +**``** + +- ``: チャート固定判定の閾値 (px) + - ARマーカーの移動量がこの値未満のフレームを「静止」とみなす. + - 例: `4.0` +- ``: チャート固定判定に必要な連続静止フレーム数 + - 例: `30` +- ``: 白色票(24色票の13番)の目標 RGB 値 + - ``: ブルー目標値 (0-255) + - ``: グリーン目標値 (0-255) + - ``: レッド目標値 (0-255) + - 例: `226`(各チャンネル共通) +- ``: ホワイトバランスゲインの更新率(0.0-1.0) + - 1.0 で即時反映,値を下げると緩やかに収束する. + - 例: `0.8` +- ``: キャリブレーションに使用するフレーム数 + - 例: `100` +- ``: ゲインを更新するフレーム間隔 + - 例: `5`(5フレームごとに更新) +- ``: 変換行列の次元数 + - 4 (1次式),10 (2次式),17 (3次式) から選択する. + - カンマ区切りで複数指定可能(例: `4,10,17`). + - 詳細は `SPEC_01_機能仕様.md` の「TCC(色変換行列)計算」を参照. + +## 撮影設定 (Shot) + +**``** + +- ``: プレビューモニタの表示幅 (px) + - 例: `1280` +- ``: 連続撮影の枚数(UI の初期値) + - 例: `10` +- ``: 連続撮影の間隔 (ms)(UI の初期値) + - 例: `500` +- ``: データ名の初期値(UI のテキストボックスに表示) + - 例: `無記名` + +## ファイル設定 (File) + +**``** + +- ``: データの保存先フォルダ(絶対パス) + - 例: `C:\TIAS_Data` +- ``: sRGB 変換参照値 CSV のパス + - 例: `tcc_srgb.csv` +- ``: XYZ 変換参照値 CSV のパス + - 例: `tcc_xyz.csv` +- ``: キャリブ時の画像ファイル名 + - 例: `TCC.png` +- ``: チャート ROI 確認画像ファイル名 + - 例: `TCC_ROIs.jpg` +- ``: 撮影画像ファイル名(`{NO}` で連番) + - 例: `Shot{NO}.png` +- ``: sRGB 変換画像ファイル名(`{CN}` で次元数,`{NO}` で連番) + - 例: `sRGB{CN}_{NO}.jpg` +- ``: 撮影情報 CSV のファイル名 + - 例: `Info.csv` +- ``: チャート RGB 値 CSV のファイル名 + - 例: `TCC_RGB.csv` +- ``: チャート sRGB 値 CSV のファイル名(`{CN}` で次元数) + - 例: `TCC_sRGB{CN}.csv` +- ``: RGB→sRGB 変換行列 CSV のファイル名 + - 例: `Conv_RGB-sRGB{CN}.csv` +- ``: RGB→XYZ 変換行列 CSV のファイル名 + - 例: `Conv_RGB-XYZ{CN}.csv` +- ``: sRGB→XYZ 変換行列 CSV のファイル名 + - 例: `Conv_sRGB-XYZ{CN}.csv` +- ``: RGB→XYZ 変換行列(旧形式)CSV のファイル名 + - 例: `Conv_RGB-XYZold.csv` + +## 光源設定 (Light Source) + +**``** + +- ``: 光源デバイスのデバイス名(部分一致で検索) + - 例: `Silicon Labs CP210x` +- ``: シリアル通信のボーレート (bps) + - 例: `38400` + +## サウンド設定 (Sound) + +**``** + +- ``: キャリブレーション完了時の効果音ファイル名 + - 例: `CalibDone.wav` +- ``: 1枚撮影完了時の効果音ファイル名 + - 例: `OneShot.wav` +- ``: 連続撮影完了時の効果音ファイル名 + - 例: `MultiShot.wav` diff --git "a/docs/04_TECH/TECH_01_\343\202\257\343\203\251\343\202\271\350\250\255\350\250\210.md" "b/docs/04_TECH/TECH_01_\343\202\257\343\203\251\343\202\271\350\250\255\350\250\210.md" new file mode 100644 index 0000000..b861ef5 --- /dev/null +++ "b/docs/04_TECH/TECH_01_\343\202\257\343\203\251\343\202\271\350\250\255\350\250\210.md" @@ -0,0 +1,87 @@ +# クラス設計 (Class Design) + +## クラス一覧 (Class Overview) + +**CameraBase(抽象基底クラス)** + +- ファイル: `CameraBase.cs` +- カメラに共通する処理をまとめた抽象クラス. +- IScam・Lucam の両方が継承する. + +**IScam** + +- ファイル: `IScam.cs` +- ImagingSource カメラ(DFK33UX178,DFK23UX249)の実装. +- IC Imaging Control SDK(`TIS.Imaging`)を使用する. + +**Lucam** + +- ファイル: `Lucam.cs` +- Lumenera カメラ(Lw110)の実装. +- Lumenera SDK(`lumenera.api.dll`)を使用する. + +**Form1** + +- ファイル: `Form1.cs` +- メインウィンドウ.UI イベントの受け取りとカメラ・光源の操作を担う. + +**PreviewMonitor** + +- ファイル: `PreviewMonitor.cs` +- サブモニタへのプレビュー表示フォーム. + +**Config(静的クラス)** + +- ファイル: `Config.cs` +- `config.xml` の読み込みユーティリティ. +- XPath を使って文字列・整数・浮動小数点数の値を取得する. + +**LightSource** + +- ファイル: `LightSource.cs` +- シリアル通信(USB-シリアル変換)による光源の ON/OFF 制御. + +## 継承関係 (Inheritance) + +```text +CameraBase(抽象) +├── IScam ← ImagingSource カメラ +└── Lucam ← Lumenera カメラ +``` + +## CameraBase の主なメンバ (CameraBase Members) + +### 抽象メソッド(派生クラスで実装する) + +- `Connect() : bool`: カメラに接続する +- `Disconnect()`: カメラを切断する +- `Shot(numImages, interval)`: 撮影処理 + +### 公開メソッド + +- `ShotOne()`: 1枚撮影 +- `ShotMulti()`: 連続撮影 + +### 保護メソッド(派生クラスから呼ぶ) + +- `BootCheck() : bool`: 起動時の前提条件チェック(設定・TCC参照ファイル) +- `DetectChart(img)`: ArUco マーカーによるチャート検出 +- `CalcTcc(img)`: TCC 変換行列の計算・保存 +- `ConvertImage(src, conv) : Mat`: 画像の色変換 +- `SaveThread(numImages)`: 画像保存スレッド処理 +- `GetRatio(value, target) : float`: ゲイン更新比率の計算 + +### 主なフィールド + +- `_calibrating`: キャリブレーション残りフレーム数(0 で完了) +- `_calibrated`: キャリブレーション完了フラグ +- `_chartMasks`: 24色票の ROI マスクリスト +- `_convRGB2SRGB`: 次元数をキーとした RGB→sRGB 変換行列の辞書 +- `_roi`: ROI 矩形(IScam のみ使用) +- `_shots`: 撮影済み画像バッファ + +## Form1 とカメラの関係 (Form1 and Camera) + +- Form1 は `CameraBase` 型の `_camera` フィールドを持つ. +- 起動時に Lucam → IScam の順で接続を試みる(詳細は `TECH_02` 参照). +- UI スレッドとカメラスレッドをまたぐメソッド(`ShowMessage`,`EnableShots` 等)は `InvokeRequired` を確認してスレッドセーフに呼び出す. diff --git "a/docs/04_TECH/TECH_02_\343\202\253\343\203\241\343\203\251\345\210\266\345\276\241\344\273\225\346\247\230.md" "b/docs/04_TECH/TECH_02_\343\202\253\343\203\241\343\203\251\345\210\266\345\276\241\344\273\225\346\247\230.md" new file mode 100644 index 0000000..adec6b7 --- /dev/null +++ "b/docs/04_TECH/TECH_02_\343\202\253\343\203\241\343\203\251\345\210\266\345\276\241\344\273\225\346\247\230.md" @@ -0,0 +1,88 @@ +# カメラ制御仕様 (Camera Control Specification) + +## 起動時のカメラ接続フロー (Startup Connection Flow) + +Form1 ロード時に以下の順で接続を試みる. + +1. `Lucam.Connect()` を実行する + - 成功: Lucam をアクティブカメラとして使用する + - 失敗: 次へ + +2. ImagingSource デバイス一覧を走査する + - 接続されているデバイス名を順に `IScam.Connect()` で試行する + - 最初に成功したカメラをアクティブカメラとして使用する + +3. どのカメラも接続できない場合 + - エラーダイアログを表示してアプリを終了する + +## IScam(ImagingSource カメラ)の制御 (IScam Control) + +### 接続 + +- `[デバイス名].xml` からカメラ設定をロードする. +- `config.xml` の `<カメラ名>/ROI` から ROI 設定を読み込む. +- `FrameQueueSink` をシンクに設定してライブ開始する. + +### プレビュー(フレーム取得コールバック) + +- `FrameQueueSink` の `Retrieve` コールバックでフレームを受け取る. +- 受け取った画像を転置(`.T()`)し,ROI を切り出して表示する. +- キャリブレーション中は白色票の測定・ゲイン更新も行う(後述). + +### ROI クリップ + +- ImagingSource カメラは横向きに画像を出力するため,転置して縦向きに変換する. +- 転置後の画像座標系で ROI(X,Y,W,H)を切り出す. + +### 撮影 + +- シンクを `FrameQueueSink` → `FrameSnapSink` に切り替える. +- `SnapSingle()` で1フレームずつ取得して `_shots` に蓄積する. +- 撮影完了後,シンクを `FrameQueueSink` に戻す. +- 最初の1フレームは捨てる(カメラの安定待ち). + +## Lucam(Lumenera カメラ)の制御 (Lucam Control) + +### 接続 + +- `LucamNumCameras()` で接続台数を確認する(0台または2台以上はエラー). +- カメラ ID から機種を特定する(`0x49f` → Lw110). +- `LucamRgbPreviewCallback` コールバックを登録する. +- `config.xml` の `` からカメラパラメータを設定して,プレビューを開始する. + +### プレビュー(フレーム取得コールバック) + +- `LucamRgbPreviewCallback` でフレームを受け取る. +- 受け取った画像を転置(`.T()`)して表示する(ROI クリップなし). +- キャリブレーション中は白色票の測定・ゲイン更新も行う(後述). + +### 撮影 + +- `LucamEnableFastFrames()` でスナップ撮影モードに切り替える. +- `LucamTakeFastFrame()` でRAW画像を取得し,`LucamConvertFrameToRgb24()` でRGB変換する. +- 撮影完了後,`LucamDisableFastFrames()` で通常モードに戻す. + +## ホワイトバランス自動調整 (White Balance Calibration) + +チャート検出後(`_calibrating` が `Calib/Frames` にセットされた後),各フレームで以下の処理を行う. + +1. 白色票(`_chartMasks[12]`,24色票の13番)の平均 RGB 値を測定する + +2. `Calib/UpdateInterval` フレームごとにゲインを更新する + - 更新比率: `ratio = (target / current - 1) * UpdateRate + 1` + - IScam: `VCDRangeProperty.Value` を直接更新する + - Lucam: `_snap.Gain*` を更新し `SetCameraParam()` で反映する + +3. `_calibrating` をデクリメントし,0 になったら `CalcTcc()` を呼び出す + +## データ保存フォルダの生成 (Save Folder) + +`SetSaveFolder(note)` が保存先フォルダを以下の書式で生成する. + +```text +[SaveFolder]/[yyyy-MM-dd]/[HH_mm_ss]-[note]/ +``` + +- `SaveFolder` は `config.xml` の `` で指定する. +- `note` は「データ名」(撮影時)または「校正」(キャリブ時). +- フォルダが存在しない場合は自動作成する. diff --git "a/docs/04_TECH/TECH_03_\350\211\262\350\243\234\346\255\243\345\207\246\347\220\206\344\273\225\346\247\230.md" "b/docs/04_TECH/TECH_03_\350\211\262\350\243\234\346\255\243\345\207\246\347\220\206\344\273\225\346\247\230.md" new file mode 100644 index 0000000..c320182 --- /dev/null +++ "b/docs/04_TECH/TECH_03_\350\211\262\350\243\234\346\255\243\345\207\246\347\220\206\344\273\225\346\247\230.md" @@ -0,0 +1,85 @@ +# 色補正処理仕様 (Color Correction Specification) + +## 処理の全体フロー (Overall Flow) + +```text +1. ArUco マーカー検出(DetectChart) + ↓ +2. チャート固定判定 + ↓ +3. ホワイトバランス自動調整(ゲイン更新) + ↓ +4. TCC 変換行列の計算(CalcTcc) + ↓ +5. 変換行列の保存・撮影の有効化 +``` + +## チャート検出(DetectChart) (Chart Detection) + +### ArUco マーカー検出 + +- 辞書: Dict4X4_50(4×4 ビット,50種) +- 使用マーカー ID: 40(チャート上端),41(チャート下端) +- 両方のマーカーが検出できない場合は処理をスキップする. +- ID40 の Y 座標が ID41 より大きい場合(上下逆)は警告を表示する. + +### チャート固定判定 + +- ID40 の検出座標と前フレームの座標の距離を計算する. +- 距離 < `Calib/ChartSetCriteria` が `Calib/ChartSetCount` フレーム連続したら固定と判断する. +- 動きを検出したらカウントをリセットする. + +### ホモグラフィ計算とチャートマスク作成 + +- 2つのマーカーの角点(計8点)からホモグラフィ行列を計算する. +- ホモグラフィで画像を 1545×810 px に正面化する. +- 正面化画像上で 24 色票の ROI を定義し(6列×4行,各 80×80 px),元の画像座標系に逆変換してマスクを生成する. +- 生成したマスクを `_chartMasks` リスト(インデックス 0〜23)に格納する. + +## TCC 変換行列の計算(CalcTcc) (TCC Matrix Calculation) + +### チャート RGB 値の取得 + +- `_chartMasks` を使って 24 パッチの平均 RGB 値を測定する(24×3 行列). + +### 多項式拡張(ExtendMat) + +3チャンネル(R,G,B)を指定の次元数に拡張する. + +**次元数と項の対応** + +| 次元数 | 追加される項 | +| --- | --- | +| 4 (1次式) | 1, R, G, B | +| 10 (2次式) | + RG, RB, GB, R², G², B² | +| 17 (3次式) | + R²B, R²G, G²R, G²B, B²R, B²G, RGB | + +- 各項は `ExtendChannels` テーブルで定義した3チャンネルの積として計算する. + +### 変換行列の算出(CalcConvertMatrix) + +- 拡張行列(24×N)と目標行列(24×3)から最小二乗法(SVD分解)で変換行列(N×3)を算出する. +- `Cv2.Solve(..., DecompTypes.SVD)` を使用する. + +### 算出する変換行列の種類 + +- RGB→sRGB: カメラ RGB から sRGB への変換行列 +- RGB→XYZ: カメラ RGB から XYZ 色空間への変換行列 +- sRGB→XYZ: sRGB から XYZ 色空間への変換行列 +- 各行列は指定した次元数ぶん計算・保存される. + +### TCC参照値ファイル + +- `tcc_srgb.csv`: 24色票の標準 sRGB 値(24×3 行列) +- `tcc_xyz.csv`: 24色票の標準 XYZ 値(24×3 行列) +- アプリ起動時に読み込み,`CameraBase` に保持する. + +## 画像の色変換(ConvertImage) (Image Color Conversion) + +1. 入力画像を `CV_64FC3`(64bit浮動小数点3チャンネル)に変換する +2. 画像を1次元(ピクセル数×3)に変形(Reshape)する +3. 多項式拡張(ExtendMat)でピクセル数×N 行列にする +4. 変換行列(N×3)を右から掛けて変換後の値を得る +5. `CV_8UC3`(8bit整数)に変換して出力する + +- 変換後の値は 0〜255 の範囲に自動クリップされる(`ConvertTo` による飽和). diff --git "a/docs/05_PLAN/PLAN_01_\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\350\250\210\347\224\273.md" "b/docs/05_PLAN/PLAN_01_\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\350\250\210\347\224\273.md" new file mode 100644 index 0000000..d8464c1 --- /dev/null +++ "b/docs/05_PLAN/PLAN_01_\343\203\252\343\203\225\343\202\241\343\202\257\343\202\277\343\203\252\343\203\263\343\202\260\350\250\210\347\224\273.md" @@ -0,0 +1,103 @@ +# リファクタリング計画 (Refactoring Plan) + +## 方針 (Policy) + +- 処理の変更は一切行わない.構造の整理のみを目的とする. +- 各フェーズ完了後に必ずテストを実施し,動作が変わっていないことを確認してから次へ進む. +- テストの具体的な手順は `TEST_01_テスト仕様.md` を参照する. + +## 現状の問題点 (Current Issues) + +`CameraBase.cs` に以下の責務が集中している. + +- カメラ制御の抽象定義(Connect/Disconnect/Shot) +- チャート検出(ArUco マーカー検出,ホモグラフィ計算,マスク生成) +- 色補正処理(TCC行列計算,多項式拡張,画像変換) +- ファイル I/O(CSV読み書き,保存フォルダ生成,撮影情報出力) +- サウンド再生 + +## 目標とするディレクトリ構成 (Target Structure) + +```text +TIASshot/ +├── Cameras/ ← カメラ制御(CameraBase, IScam, Lucam) +├── ChartDetection/ ← チャート検出(CameraBaseから分離) +├── ColorCorrection/ ← 色補正・TCC計算(CameraBaseから分離) +├── UI/ ← フォーム(Form1, PreviewMonitor) +├── Config.cs ← 設定ファイル読み込み(変更なし) +├── LightSource.cs ← 光源制御(変更なし) +└── Program.cs ← エントリポイント(変更なし) +``` + +## フェーズ構成 (Phases) + +### フェーズ1: フォルダ整理とファイル移動 + +**作業内容** + +- 以下のフォルダを作成し,既存ファイルを移動する. + - `Cameras/` ← CameraBase.cs, IScam.cs, Lucam.cs + - `UI/` ← Form1.cs, Form1.Designer.cs, Form1.resx, PreviewMonitor.cs, PreviewMonitor.Designer.cs, PreviewMonitor.resx +- 名前空間(namespace)はそのまま `TIASshot` で統一する. +- ファイルの中身は変更しない. + +**テスト** + +- ビルドが成功することを確認する. +- アプリが起動し,カメラが接続されることを確認する(手動). + +### フェーズ2: 色補正処理の分離 + +**作業内容** + +- `ColorCorrection/` フォルダを作成する. +- CameraBase から以下を新クラス `ColorCorrector` に切り出す. + - フィールド: `TCC_SRGB`, `TCC_XYZ`, `ChannelList`, `ExtendChannels`, `UpdateRate` + - メソッド: `ExtendMat`, `CalcConvertMatrix`, `ConvertColor`, `ConvertImage` + - メソッド: `CalcTcc`(チャート RGB 値の受け取りと行列計算・保存を担当) +- CameraBase は `ColorCorrector` を保持し,処理を委譲する. + +**テスト** + +- ビルドが成功することを確認する. +- 回帰テスト: 同一入力画像から算出した変換行列が,リファクタリング前と一致することを確認する. + - 具体的な手順は `TEST_01_テスト仕様.md` の「回帰テスト: 色補正処理」を参照する. + +### フェーズ3: チャート検出処理の分離 + +**作業内容** + +- `ChartDetection/` フォルダを作成する. +- CameraBase から以下を新クラス `ChartDetector` に切り出す. + - フィールド: `ARDict`, `PointsDst40`, `PointsDst41`, `_detectionCount`, `_lastPosition` + - メソッド: `DetectChart` + - 出力: チャートマスクリスト(`List`)を戻り値または引数で渡す +- CameraBase は `ChartDetector` を保持し,処理を委譲する. + +**テスト** + +- ビルドが成功することを確認する. +- 回帰テスト: 保存済みの実画像を入力として,チャートマスクの位置が一致することを確認する. + - 具体的な手順は `TEST_01_テスト仕様.md` の「チャート検出テスト」を参照する. + +### フェーズ4: ファイル I/O・サウンドの分離 + +**作業内容** + +- CameraBase から以下をユーティリティクラスとして切り出す(配置先は `Cameras/` または新フォルダ). + - `LoadMatFromCsv`, `SaveMatToCsv` + - `SetSaveFolder`, `WriteInfo` + - `EventSound` + +**テスト** + +- ビルドが成功することを確認する. +- 撮影からファイル保存までの一連の動作を手動で確認する. +- 保存された CSV・画像の内容がリファクタリング前と一致することを確認する. + +## 共通ルール (Common Rules) + +- 各フェーズは独立したブランチではなく,`refactor/code-cleanup` ブランチ上で順に進める. +- フェーズ完了ごとにコミットする.コミットメッセージは `[clean]` タグを使用する. + - 例: `[clean] 色補正処理を ColorCorrector クラスに分離` +- テストが通らない場合は,次のフェーズに進まない. diff --git "a/docs/05_PLAN/PLAN_02_\343\203\220\343\202\260\344\277\256\346\255\243\350\250\210\347\224\273.md" "b/docs/05_PLAN/PLAN_02_\343\203\220\343\202\260\344\277\256\346\255\243\350\250\210\347\224\273.md" new file mode 100644 index 0000000..2d3d5fb --- /dev/null +++ "b/docs/05_PLAN/PLAN_02_\343\203\220\343\202\260\344\277\256\346\255\243\350\250\210\347\224\273.md" @@ -0,0 +1,115 @@ +# バグ修正計画 (Bug Fix Plan) + +## 前提 (Prerequisites) + +- `PLAN_01_リファクタリング計画.md` の全フェーズが完了し,動作がリファクタリング前と同一であることを確認してから着手する. +- 修正は1件ずつ独立して行い,都度テストを実施する. +- コミットメッセージは `[fix]` タグを使用する. + - 例: `[fix] _shots へのスレッドセーフなアクセスに修正` + +## 症状 (Symptom) + +- 連続撮影で4枚以上取得するとアプリがたまにクラッシュする. +- 再現性は不安定(毎回ではなく「たまに」落ちる). + +## 原因と修正方針 (Causes and Fix Policy) + +### 優先度1: `_shots` へのスレッドセーフでないアクセス(根本原因) + +**原因** + +`_shots`(`List`)は Shot スレッドと SaveThread から同時にアクセスされる. +`List` はスレッドセーフではないため,以下の2点で競合が発生する. + +- リサイズ競合 + - `List` の内部配列は容量が足りなくなると自動で拡張される(デフォルト容量 4 → 5枚目の Add 時に 8 に拡張). + - 拡張中に SaveThread が `_shots[saveCount]` を読むとメモリ破壊が起きる. + - 「4枚以上でたまに落ちる」という症状に一致する. +- TOCTOU(確認と使用の間の競合) + - SaveThread の `_shots.Count` チェックと `_shots[saveCount]` アクセスの間に Shot スレッドがリサイズを起こすと `IndexOutOfRangeException` が発生する. + +**修正方針** + +- `_shots` を `List` から `System.Collections.Concurrent.ConcurrentQueue` またはロック付きアクセスに変更する. +- SaveThread の待機ロジックをスレッドセーフな方法(`SemaphoreSlim` 等)に変更する. + +**テスト** + +- 連続撮影を10枚以上で複数回繰り返し,クラッシュしないことを確認する. + +### 優先度2: `ConvertImage` 内の Mat 未 Dispose によるメモリ蓄積 + +**原因** + +`ConvertImage` 内で生成される中間 Mat(`extended`,`converted`,`convertedImage`)が Dispose されないまま残る. +1回の呼び出しで数百 MB〜1 GB 超が蓄積し,画像枚数×チャンネル数分だけ積み重なる. +(例: IScam 1840×2440,17次元,4枚連続撮影 → 数十 GB 規模) + +**修正方針** + +- `extended`,`converted`,`convertedImage` を `using` ブロックで管理して確実に Dispose する. + +**テスト** + +- タスクマネージャでメモリ使用量を監視しながら連続撮影を繰り返し,撮影ごとにメモリが増加し続けないことを確認する. + +### 優先度3: `Parallel.For` 内での未捕捉例外 + +**原因** + +`ExtendMat` の `Parallel.For` 内で OOM 等の例外が発生した場合,`AggregateException` としてラップされて SaveThread に伝播する. +SaveThread で捕捉されなければアプリがクラッシュする. +※ 優先度2の修正でメモリ蓄積が解消されれば,発生頻度は大幅に下がる. + +**修正方針** + +- SaveThread に例外ハンドラを追加し,クラッシュではなくエラーメッセージを表示して処理を中断するようにする. +- `ExtendMat` の `Parallel.For` に try-catch を追加する. + +**テスト** + +- 例外発生時にアプリが落ちずエラーが表示されることを確認する. + +### 優先度4: `ConvertImage` による `_shots[i]` の in-place 書き換え + +**原因** + +`ConvertImage` 内の `src.ConvertTo(src, CV_64FC3)` が `_shots[i]` 自体を CV_8UC3 から CV_64FC3 に書き換える副作用がある. +特に IScam の `new Mat(imgt_full, _roi)`(サブマトリクス)に対して in-place の型変換を行うと不正な動作を引き起こす可能性がある. +また複数チャンネルを処理する際,2回目以降は変換済みのデータに対して処理をかけることになり,変換結果が誤る. + +**修正方針** + +- `ConvertImage` の冒頭で `src` をコピーし,コピー側を変換するようにする(`src` を直接書き換えない). + +**テスト** + +- 複数チャンネル(例: `4,10,17`)で撮影し,各チャンネルの sRGB 変換画像が正しく出力されることを確認する. + +### 優先度5: Mat 未 Dispose によるメモリリーク + +**原因 A: `_shots.Clear()` で Mat が解放されない** + +- 撮影ごとに `_shots.Clear()` が呼ばれるが,格納された Mat は Dispose されない. + +**原因 B: `_chartMasks.Clear()` で Mat が解放されない** + +- チャート再検出時に `_chartMasks.Clear()` が呼ばれるが,同様に Dispose されない. + +**修正方針** + +- Clear 前に各 Mat を Dispose するヘルパーを追加する. + +**テスト** + +- タスクマネージャでメモリ使用量を監視し,撮影・キャリブを繰り返してもメモリが増加し続けないことを確認する. + +## 修正順序まとめ (Summary) + +| 順位 | 原因 | クラッシュとの関連 | +| --- | --- | --- | +| 1 | `_shots` のスレッドセーフでないアクセス | 直接原因(「たまに落ちる」に一致) | +| 2 | `ConvertImage` 内の Mat 未 Dispose | 直接原因(OOM によるクラッシュ) | +| 3 | `Parallel.For` 内の未捕捉例外 | 間接原因(2の修正で頻度減) | +| 4 | `ConvertImage` の in-place 書き換え | 誤動作(変換結果の誤り) | +| 5 | `_shots` / `_chartMasks` の Mat 未 Dispose | メモリリーク(蓄積) | diff --git "a/docs/06_TEST/TEST_01_\343\203\206\343\202\271\343\203\210\344\273\225\346\247\230.md" "b/docs/06_TEST/TEST_01_\343\203\206\343\202\271\343\203\210\344\273\225\346\247\230.md" new file mode 100644 index 0000000..fc177bf --- /dev/null +++ "b/docs/06_TEST/TEST_01_\343\203\206\343\202\271\343\203\210\344\273\225\346\247\230.md" @@ -0,0 +1,91 @@ +# テスト仕様 (Test Specification) + +## 方針 (Policy) + +リファクタリングによって処理が変わっていないことを確認するためのテスト仕様. +各フェーズの適用タイミングは `PLAN_01_リファクタリング計画.md` を参照する. + +テストの種類: + +- ビルドテスト: コンパイルエラーがないことを確認する +- 回帰テスト: リファクタリング前後の出力が一致することを確認する +- 手動テスト: 実機を使って動作を目視確認する + +## ビルドテスト (Build Test) + +全フェーズで実施する. + +**手順** + +1. Visual Studio で「ビルド」→「ソリューションのビルド」を実行する +2. エラーが0件であることを確認する +3. 警告が増加していないことを確認する(リファクタリング前の警告数を記録しておく) + +**合格条件** + +- ビルドエラーが0件 + +## 回帰テスト: 色補正処理(フェーズ2) + +リファクタリング前に基準データを作成し,リファクタリング後の出力と比較する. + +### 基準データの作成(リファクタリング前に実施) + +1. 実機でキャリブレーションを実行する +2. 保存された以下のファイルを「基準データ」として別フォルダに保管する + - `TCC_RGB.csv` ← チャート24色票のRGB値 + - `Conv_RGB-sRGB{CN}.csv` ← RGB→sRGB 変換行列 + - `Conv_RGB-XYZ{CN}.csv` ← RGB→XYZ 変換行列 + - `Conv_sRGB-XYZ{CN}.csv` ← sRGB→XYZ 変換行列 + - `TCC_sRGB{CN}.csv` ← チャートのsRGB変換値 + - `sRGB{CN}_0001.jpg` ← 撮影した sRGB 変換画像1枚 + +### 比較(リファクタリング後に実施) + +1. 同一のキャリブレーション画像・撮影条件で再度実行する + - ※ 実機でのキャリブレーション再現が困難な場合は,TCC_RGB.csv を直接入力として行列計算のみ比較する +2. 基準データと出力ファイルを比較する + +**合格条件** + +- CSV の数値が全行・全列で一致する(または浮動小数点誤差 ±1e-6 以内) +- 画像のピクセル値が全ピクセルで一致する + +## チャート検出テスト(フェーズ3) + +保存済みの実画像を入力として,チャートマスクの位置を比較する. + +### 基準データの作成(リファクタリング前に実施) + +1. キャリブレーション時に保存される `TCC_ROIs.jpg` を基準データとして保管する + - ※ TCC_ROIs.jpg はチャートの ROI マスク位置を緑色で重ねた確認画像 + +### 比較(リファクタリング後に実施) + +1. 同一条件でキャリブレーションを実行する +2. 出力された `TCC_ROIs.jpg` を基準データと目視比較する + - ※ 緑色のマスク位置が完全に一致していることを確認する + +**合格条件** + +- マスクの位置・形状が基準データと目視で一致する + +## 手動テスト(全フェーズ) + +実機を使った動作確認.フェーズごとに実施する. + +**確認項目** + +- アプリが正常に起動する +- カメラが自動で接続される(Lucam または ImagingSource) +- プレビューが表示される +- 舌診チャートを映すとキャリブレーションが自動開始される +- キャリブレーション完了後に撮影ボタンが有効になる +- 1枚撮影が正常に完了し,ファイルが保存される +- 連続撮影が正常に完了し,ファイルが保存される +- 光源の ON/OFF が切り替わる +- アプリを閉じてもエラーが出ない + +**合格条件** + +- 上記の全項目でエラー・クラッシュが発生しない diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md new file mode 100644 index 0000000..14ea2fc --- /dev/null +++ b/docs/PROGRESS.md @@ -0,0 +1,11 @@ +# 開発進捗ログ + + diff --git a/setup.ps1 b/setup.ps1 new file mode 100644 index 0000000..8679da3 --- /dev/null +++ b/setup.ps1 @@ -0,0 +1,105 @@ +# ============================================================================= +# TIASshot 開発環境セットアップスクリプト +# 実行方法: PowerShell を管理者権限で開き,以下を実行する +# Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass +# .\setup.ps1 +# ============================================================================= + +$ErrorActionPreference = "Stop" + +Write-Host "========================================" -ForegroundColor Cyan +Write-Host " TIASshot 開発環境セットアップ" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" + +# ----------------------------------------------------------------------------- +# Step 1: Visual Studio 2022 のインストール +# ----------------------------------------------------------------------------- +Write-Host "[Step 1] Visual Studio 2022 のインストール確認..." -ForegroundColor Yellow + +$vsInstalled = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ` + -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*Visual Studio*2022*" } +if ($vsInstalled) { + Write-Host " Visual Studio はインストール済みです.スキップします." -ForegroundColor Green +} else { + Write-Host " Visual Studio 2022 をインストールします..." -ForegroundColor White + $vsconfigPath = Join-Path $PSScriptRoot ".vsconfig" + winget install Microsoft.VisualStudio.2022.Community --no-upgrade ` + --override "--config `"$vsconfigPath`" --quiet --wait" + Write-Host " インストール完了." -ForegroundColor Green +} + +Write-Host "" + +# ----------------------------------------------------------------------------- +# Step 2: データ保存フォルダの作成 +# ----------------------------------------------------------------------------- +Write-Host "[Step 2] データ保存フォルダの作成..." -ForegroundColor Yellow + +$dataFolder = "C:\TIAS_Data" +if (Test-Path $dataFolder) { + Write-Host " $dataFolder は既に存在します.スキップします." -ForegroundColor Green +} else { + New-Item -ItemType Directory -Path $dataFolder | Out-Null + Write-Host " $dataFolder を作成しました." -ForegroundColor Green +} + +Write-Host "" + +# ----------------------------------------------------------------------------- +# Step 3: NuGet パッケージの復元 +# ----------------------------------------------------------------------------- +Write-Host "[Step 3] NuGet パッケージの復元..." -ForegroundColor Yellow + +$slnPath = Join-Path $PSScriptRoot "TIASshot.sln" +if (Test-Path $slnPath) { + # nuget.exe が PATH になければリポジトリルートにダウンロードして使用する + $nugetCmd = Get-Command nuget.exe -ErrorAction SilentlyContinue + if ($nugetCmd) { + $nugetExe = "nuget.exe" + } else { + $nugetExe = Join-Path $PSScriptRoot "nuget.exe" + if (-not (Test-Path $nugetExe)) { + Write-Host " nuget.exe をダウンロードします..." -ForegroundColor White + Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" ` + -OutFile $nugetExe + } + } + & $nugetExe restore $slnPath + Write-Host " NuGet パッケージの復元が完了しました." -ForegroundColor Green +} else { + Write-Host " TIASshot.sln が見つかりません.手動で復元してください." -ForegroundColor Red +} + +Write-Host "" + +# ----------------------------------------------------------------------------- +# Step 4: IC Imaging Control SDK(手動インストール案内) +# ----------------------------------------------------------------------------- +Write-Host "[Step 4] IC Imaging Control SDK のインストール確認..." -ForegroundColor Yellow + +$icInstalled = Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ` + -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*Imaging*" -or $_.DisplayName -like "*IC Imaging*" } +if ($icInstalled) { + Write-Host " IC Imaging Control SDK はインストール済みです.スキップします." -ForegroundColor Green +} else { + Write-Host " IC Imaging Control SDK が見つかりません." -ForegroundColor White + Write-Host " ブラウザで The Imaging Source のダウンロードページを開きます." -ForegroundColor White + Start-Process "https://www.theimagingsource.com/en-us/support/download/" +} + +Write-Host "" + +# ----------------------------------------------------------------------------- +# 完了メッセージ +# ----------------------------------------------------------------------------- +Write-Host "========================================" -ForegroundColor Cyan +Write-Host " セットアップが完了しました" -ForegroundColor Cyan +Write-Host "========================================" -ForegroundColor Cyan +Write-Host "" +Write-Host "次の手順を手動で実施してください:" -ForegroundColor Yellow +Write-Host " 1. IC Imaging Control SDK のインストール(Step 4 参照)" +Write-Host " 2. TIASshot.sln を Visual Studio 2022 で開いてビルド確認" +Write-Host " 3. config.xml・カメラ設定ファイル・CSV ファイルの配置" +Write-Host " (詳細は docs\02_ENV\ENV_01_開発環境構築手順.md を参照)" +Write-Host ""