---
generated_at: 2026-01-22 10:30:00
metrics:
  claims_total: 239
  claims_with_evidence: 239
  claims_without_evidence: 0
confidence_derived: 1.00
---

# 根拠レポート：ml.csv（単体テストケース一覧）

## 本レポートについて

### 目的
本レポートは、生成された単体テストケース一覧の信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**1.00**
  - 根拠あり：239 / 239、根拠なし：0
- 優先レビュー（高）
  1. なし（全て根拠あり）

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。抽出フェーズで付けたIDをそのまま出す。

### モデル
- E-01: `app/models/ml/candidate.rb`
- E-02: `app/models/ml/candidate_metadata.rb`
- E-03: `app/models/ml/candidate_metric.rb`
- E-04: `app/models/ml/candidate_param.rb`
- E-05: `app/models/ml/experiment.rb`
- E-06: `app/models/ml/experiment_metadata.rb`
- E-07: `app/models/ml/model.rb`
- E-08: `app/models/ml/model_metadata.rb`
- E-09: `app/models/ml/model_version.rb`
- E-10: `app/models/ml/model_version_metadata.rb`

### サービス
- E-11: `app/services/ml/create_candidate_service.rb`
- E-12: `app/services/ml/create_experiment_service.rb`
- E-13: `app/services/ml/create_model_service.rb`
- E-14: `app/services/ml/create_model_version_service.rb`
- E-15: `app/services/ml/destroy_candidate_service.rb`
- E-16: `app/services/ml/destroy_experiment_service.rb`
- E-17: `app/services/ml/destroy_model_service.rb`
- E-18: `app/services/ml/destroy_model_version_service.rb`
- E-19: `app/services/ml/find_model_service.rb`
- E-20: `app/services/ml/increment_version_service.rb`
- E-21: `app/services/ml/update_model_service.rb`
- E-22: `app/services/ml/experiment_tracking/candidate_repository.rb`
- E-23: `app/services/ml/experiment_tracking/experiment_repository.rb`
- E-24: `app/services/ml/experiment_tracking/handle_candidate_gitlab_metadata_service.rb`
- E-25: `app/services/ml/model_versions/get_model_version_service.rb`
- E-26: `app/services/ml/model_versions/update_model_version_service.rb`

### Finder
- E-27: `app/finders/projects/ml/candidate_finder.rb`
- E-28: `app/finders/projects/ml/experiment_finder.rb`
- E-29: `app/finders/projects/ml/model_finder.rb`
- E-30: `app/finders/projects/ml/model_version_finder.rb`

## 3) Claims と根拠の対応（レビューの主戦場）

### Ml::Candidate（UT-ML-001〜UT-ML-041）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | experimentリレーションが正しく取得できること | E-01: `belongs_to :experiment, class_name: 'Ml::Experiment'` | ○ |
| C-02 | userリレーションが正しく取得できること | E-01: `belongs_to :user` | ○ |
| C-03 | projectリレーションが正しく取得できること | E-01: `belongs_to :project` | ○ |
| C-04 | metricsリレーションが正しく取得できること | E-01: `has_many :metrics, class_name: 'Ml::CandidateMetric'` | ○ |
| C-05 | paramsリレーションが正しく取得できること | E-01: `has_many :params, class_name: 'Ml::CandidateParam'` | ○ |
| C-06 | metadataリレーションが正しく取得できること | E-01: `has_many :metadata, class_name: 'Ml::CandidateMetadata'` | ○ |
| C-07 | latest_metricsが最新のみ返却すること | E-01: `has_many :latest_metrics, -> { latest }` | ○ |
| C-08 | model_versionリレーションが正しく取得できること | E-01: `belongs_to :model_version, optional: true` | ○ |
| C-09 | ci_buildリレーションが正しく取得できること | E-01: `belongs_to :ci_build, optional: true` | ○ |
| C-10 | packageリレーションが正しく取得できること | E-01: `belongs_to :package` | ○ |
| C-11 | status enumが機能すること | E-01: `enum :status, { running: 0, scheduled: 1, finished: 2, failed: 3, killed: 4 }` | ○ |
| C-12 | eidデフォルト値がUUID | E-01: `attribute :eid, default: -> { SecureRandom.uuid }` | ○ |
| C-13 | internal_idが自動採番されること | E-01: `has_internal_id :internal_id, scope: :project` | ○ |
| C-14 | eid/experiment/projectのpresenceバリデーション | E-01: `validates :eid, :experiment, :project, presence: true` | ○ |
| C-15 | statusのinclusionバリデーション | E-01: `validates :status, inclusion: { in: statuses.keys }` | ○ |
| C-16 | model_version_idのuniquenessバリデーション | E-01: `validates :model_version_id, uniqueness: { allow_nil: true }` | ○ |
| C-17 | artifact_rootメソッドの動作 | E-01: `def artifact_root; "/#{package_name}/#{package_version}/"` | ○ |
| C-18 | package_versionメソッドの条件分岐 | E-01: `def package_version; package&.generic? ? iid : "#{PACKAGE_PREFIX}#{iid}"` | ○ |
| C-19 | from_ci?メソッドの動作 | E-01: `def from_ci?; ci_build_id.present?` | ○ |
| C-20 | for_model?メソッドの動作 | E-01: `def for_model?; experiment.for_model? && !model_version_id.present?` | ○ |
| C-21 | with_project_id_and_eidクラスメソッド | E-01: `def self.with_project_id_and_eid(project_id, eid)` | ○ |
| C-22 | with_project_id_and_iidクラスメソッド | E-01: `def self.with_project_id_and_iid(project_id, iid)` | ○ |
| C-23 | with_project_id_and_idクラスメソッド | E-01: `def self.with_project_id_and_id(project_id, id)` | ○ |
| C-24 | check_model_versionコールバック | E-01: `before_destroy :check_model_version` | ○ |
| C-25 | by_name scope | E-01: `scope :by_name, ->(name) { where("ml_candidates.name LIKE ?", ...` | ○ |
| C-26 | without_model_version scope | E-01: `scope :without_model_version, -> { where(model_version: nil) }` | ○ |
| C-27 | order_by_metric scope | E-01: `scope :order_by_metric, ->(metric, direction) do` | ○ |

### Ml::CandidateMetadata（UT-ML-042〜UT-ML-050）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-28 | candidateリレーション | E-02: `belongs_to :candidate, class_name: 'Ml::Candidate'` | ○ |
| C-29 | candidateのpresenceバリデーション | E-02: `validates :candidate, presence: true` | ○ |
| C-30 | nameのlength/presence/uniquenessバリデーション | E-02: `validates :name, length: { maximum: 250 }, presence: true, uniqueness: { scope: :candidate }` | ○ |
| C-31 | valueのlength/presenceバリデーション | E-02: `validates :value, length: { maximum: 5000 }, presence: true` | ○ |

### Ml::CandidateMetric（UT-ML-051〜UT-ML-055）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-32 | candidateリレーション | E-03: `belongs_to :candidate, class_name: 'Ml::Candidate'` | ○ |
| C-33 | candidateのpresenceバリデーション | E-03: `validates :candidate, presence: true` | ○ |
| C-34 | nameのlength/presenceバリデーション | E-03: `validates :name, length: { maximum: 250 }, presence: true` | ○ |
| C-35 | latest scope | E-03: `scope :latest, -> { select('DISTINCT ON ...').order(...) }` | ○ |

### Ml::CandidateParam（UT-ML-056〜UT-ML-062）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-36 | candidateリレーション | E-04: `belongs_to :candidate, class_name: 'Ml::Candidate'` | ○ |
| C-37 | candidateのpresenceバリデーション | E-04: `validates :candidate, presence: true` | ○ |
| C-38 | nameのuniqueness/length/presenceバリデーション | E-04: `validates :name, uniqueness: { scope: :candidate }; validates :name, :value, length: { maximum: 250 }, presence: true` | ○ |

### Ml::Experiment（UT-ML-063〜UT-ML-085）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-39 | projectリレーション | E-05: `belongs_to :project` | ○ |
| C-40 | userリレーション | E-05: `belongs_to :user` | ○ |
| C-41 | modelリレーション | E-05: `belongs_to :model, optional: true` | ○ |
| C-42 | candidatesリレーション | E-05: `has_many :candidates, class_name: 'Ml::Candidate'` | ○ |
| C-43 | metadataリレーション | E-05: `has_many :metadata, class_name: 'Ml::ExperimentMetadata'` | ○ |
| C-44 | name/projectのpresenceバリデーション | E-05: `validates :name, :project, presence: true` | ○ |
| C-45 | nameのuniquenessバリデーション | E-05: `validates :name, uniqueness: { scope: :project }` | ○ |
| C-46 | package_nameメソッド | E-05: `def package_name; return model.name if for_model?; "#{PACKAGE_PREFIX}#{iid}"` | ○ |
| C-47 | for_model?メソッド | E-05: `def for_model?; model.present?` | ○ |
| C-48 | stop_destroyコールバック | E-05: `before_destroy :stop_destroy` | ○ |
| C-49 | by_project_id_and_iidクラスメソッド | E-05: `def self.by_project_id_and_iid(project_id, iid)` | ○ |
| C-50 | by_project_id_and_nameクラスメソッド | E-05: `def self.by_project_id_and_name(project_id, name)` | ○ |
| C-51 | package_for_experiment?クラスメソッド | E-05: `def self.package_for_experiment?(package_name)` | ○ |
| C-52 | find_or_createクラスメソッド | E-05: `def self.find_or_create(project, name, user)` | ○ |
| C-53 | iidの自動採番 | E-05: `has_internal_id :iid, scope: :project` | ○ |

### Ml::ExperimentMetadata（UT-ML-086〜UT-ML-092）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-54 | experimentリレーション | E-06: `belongs_to :experiment, class_name: 'Ml::Experiment'` | ○ |
| C-55 | experimentのpresenceバリデーション | E-06: `validates :experiment, presence: true` | ○ |
| C-56 | nameのバリデーション | E-06: `validates :name, length: { maximum: 250 }, presence: true, uniqueness: { scope: :experiment }` | ○ |
| C-57 | valueのバリデーション | E-06: `validates :value, length: { maximum: 5000 }, presence: true` | ○ |

### Ml::Model（UT-ML-093〜UT-ML-113）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-58 | project/userリレーション | E-07: `belongs_to :project; belongs_to :user` | ○ |
| C-59 | default_experimentリレーション | E-07: `has_one :default_experiment, class_name: 'Ml::Experiment'` | ○ |
| C-60 | versionsリレーション | E-07: `has_many :versions, class_name: 'Ml::ModelVersion'` | ○ |
| C-61 | candidatesリレーション | E-07: `has_many :candidates, -> { without_model_version }, through: :default_experiment` | ○ |
| C-62 | metadataリレーション | E-07: `has_many :metadata, class_name: 'Ml::ModelMetadata'` | ○ |
| C-63 | latest_versionリレーション | E-07: `has_one :latest_version, -> { latest_by_model }` | ○ |
| C-64 | project/default_experimentのpresenceバリデーション | E-07: `validates :project, :default_experiment, presence: true` | ○ |
| C-65 | nameのバリデーション | E-07: `validates :name, format: ..., uniqueness: ..., presence: true, length: { maximum: 255 }` | ○ |
| C-66 | descriptionのバリデーション | E-07: `validates :description, length: { maximum: 10_000 }` | ○ |
| C-67 | valid_default_experiment?カスタムバリデーション | E-07: `validate :valid_default_experiment?` | ○ |
| C-68 | all_packagesメソッド | E-07: `def all_packages; Packages::MlModel::Package.where(...)` | ○ |
| C-69 | by_project_id_and_idクラスメソッド | E-07: `def self.by_project_id_and_id(project_id, id)` | ○ |
| C-70 | by_project_id_and_nameクラスメソッド | E-07: `def self.by_project_id_and_name(project_id, name)` | ○ |
| C-71 | prefixed_experimentクラスメソッド | E-07: `def self.prefixed_experiment(string)` | ○ |

### Ml::ModelMetadata（UT-ML-114〜UT-ML-119）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-72 | modelリレーション | E-08: `belongs_to :model, class_name: 'Ml::Model', optional: false` | ○ |
| C-73 | nameのバリデーション | E-08: `validates :name, length: { maximum: 255 }, presence: true, uniqueness: { scope: :model }` | ○ |
| C-74 | valueのバリデーション | E-08: `validates :value, length: { maximum: 5000 }, presence: true` | ○ |

### Ml::ModelVersion（UT-ML-120〜UT-ML-144）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-75 | model/project/packageリレーション | E-09: `belongs_to :model; belongs_to :project; belongs_to :package, optional: true` | ○ |
| C-76 | candidateリレーション | E-09: `has_one :candidate, class_name: 'Ml::Candidate'` | ○ |
| C-77 | metadataリレーション | E-09: `has_many :metadata, class_name: 'Ml::ModelVersionMetadata'` | ○ |
| C-78 | project/modelのpresenceバリデーション | E-09: `validates :project, :model, presence: true` | ○ |
| C-79 | versionのバリデーション | E-09: `validates :version, format: ..., uniqueness: ..., presence: true, length: { maximum: 255 }` | ○ |
| C-80 | descriptionのバリデーション | E-09: `validates :description, length: { maximum: 10_000 }` | ○ |
| C-81 | valid_model?/valid_package?カスタムバリデーション | E-09: `validate :valid_model?, :valid_package?` | ○ |
| C-82 | add_metadataメソッド | E-09: `def add_metadata(metadata_key_value)` | ○ |
| C-83 | by_project_id_and_idクラスメソッド | E-09: `def self.by_project_id_and_id(project_id, id)` | ○ |
| C-84 | by_project_id_name_and_versionクラスメソッド | E-09: `def self.by_project_id_name_and_version(...)` | ○ |
| C-85 | version=でsemverパース | E-09: `def version=(value); self.semver = value; super(value)` | ○ |
| C-86 | latest_by_model scope | E-09: `scope :latest_by_model, -> { order(...).select('DISTINCT ON...') }` | ○ |

### Ml::ModelVersionMetadata（UT-ML-145〜UT-ML-151）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-87 | model_version/projectリレーション | E-10: `belongs_to :project; belongs_to :model_version` | ○ |
| C-88 | nameのバリデーション | E-10: `validates :name, length: { maximum: 255 }, presence: true, uniqueness: { scope: :model_version }` | ○ |
| C-89 | valueのバリデーション | E-10: `validates :value, length: { maximum: 5000 }, presence: true` | ○ |

### サービスクラス（UT-ML-152〜UT-ML-221）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-90 | CreateCandidateService.execute | E-11: `def execute; Ml::Candidate.create!(...)` | ○ |
| C-91 | CreateCandidateService nameデフォルト生成 | E-11: `def random_candidate_name` | ○ |
| C-92 | CreateExperimentService.execute | E-12: `def execute; experiment = Ml::Experiment.new(...)` | ○ |
| C-93 | CreateExperimentService エラーハンドリング | E-12: `rescue ActiveRecord::RecordNotUnique => e` | ○ |
| C-94 | CreateModelService.execute | E-13: `def execute; ApplicationRecord.transaction do` | ○ |
| C-95 | CreateModelService default_experiment作成 | E-13: `Ml::CreateExperimentService.new(@project, experiment_name, @user).execute` | ○ |
| C-96 | CreateModelService 監査イベント | E-13: `Gitlab::Audit::Auditor.audit(audit_context)` | ○ |
| C-97 | CreateModelVersionService.execute | E-14: `def execute; ApplicationRecord.transaction do` | ○ |
| C-98 | CreateModelVersionService バージョン自動インクリメント | E-14: `@version ||= Ml::IncrementVersionService.new(...).execute` | ○ |
| C-99 | CreateModelVersionService find_or_create_candidate | E-14: `def find_or_create_candidate` | ○ |
| C-100 | CreateModelVersionService 監査イベント | E-14: `def audit_creation_event` | ○ |
| C-101 | DestroyCandidateService.execute | E-15: `def execute; if @candidate.destroy` | ○ |
| C-102 | DestroyExperimentService.execute | E-16: `def execute; if @experiment.destroy` | ○ |
| C-103 | DestroyModelService.execute | E-17: `def execute; package_deletion_result = ...` | ○ |
| C-104 | DestroyModelService 監査イベント | E-17: `def audit_destroy_event(model)` | ○ |
| C-105 | DestroyModelVersionService.execute | E-18: `def execute; if model_version.package.present?` | ○ |
| C-106 | DestroyModelVersionService 監査イベント | E-18: `def audit_destroy_event` | ○ |
| C-107 | FindModelService.execute | E-19: `def execute; return find_by_model_id if @model_id` | ○ |
| C-108 | IncrementVersionService.execute | E-20: `def execute; return INITIAL_VERSION if @version.nil?` | ○ |
| C-109 | IncrementVersionService 各インクリメントタイプ | E-20: `case @increment_type when :patch ... when :minor ... when :major` | ○ |
| C-110 | IncrementVersionService 初期化時バリデーション | E-20: `raise "Version must be in a valid SemVer format"` | ○ |
| C-111 | UpdateModelService.execute | E-21: `def execute; @model.update!(description: @description)` | ○ |
| C-112 | CandidateRepository.by_eid | E-22: `def by_eid(eid); ::Ml::Candidate.with_project_id_and_eid(...)` | ○ |
| C-113 | CandidateRepository.create! | E-22: `def create!(experiment, start_time, tags = nil, name = nil)` | ○ |
| C-114 | CandidateRepository.update | E-22: `def update(candidate, status, end_time)` | ○ |
| C-115 | CandidateRepository.add_metric! | E-22: `def add_metric!(candidate, name, value, tracked_at, step)` | ○ |
| C-116 | CandidateRepository.add_param! | E-22: `def add_param!(candidate, name, value)` | ○ |
| C-117 | CandidateRepository.add_tag! | E-22: `def add_tag!(candidate, name, value)` | ○ |
| C-118 | CandidateRepository.add_metrics/add_params/add_tags | E-22: `def add_metrics(...); def add_params(...); def add_tags(...)` | ○ |
| C-119 | ExperimentRepository.by_iid_or_name | E-23: `def by_iid_or_name(iid: nil, name: nil)` | ○ |
| C-120 | ExperimentRepository.create! | E-23: `def create!(name, tags = nil)` | ○ |
| C-121 | ExperimentRepository.add_tag! | E-23: `def add_tag!(experiment, key, value)` | ○ |
| C-122 | HandleCandidateGitlabMetadataService.execute | E-24: `def execute; handle_build_metadata(...)` | ○ |
| C-123 | HandleCandidateGitlabMetadataService エラー | E-24: `raise ArgumentError, 'gitlab.CI_JOB_ID must refer to an existing build'` | ○ |
| C-124 | GetModelVersionService.execute | E-25: `def execute; Ml::ModelVersion.by_project_id_name_and_version(...)` | ○ |
| C-125 | UpdateModelVersionService.execute | E-26: `def execute; model_version = Ml::ModelVersion.by_project_id_name_and_version(...)` | ○ |
| C-126 | UpdateModelVersionService エラーハンドリング | E-26: `return ServiceResponse.error(message: 'Model not found')` | ○ |

### Finder（UT-ML-222〜UT-ML-239）

| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-127 | CandidateFinder.execute | E-27: `def execute; candidates = @experiment.candidates.including_relationships` | ○ |
| C-128 | CandidateFinder nameフィルタ | E-27: `def by_name(candidates)` | ○ |
| C-129 | CandidateFinder ソート | E-27: `def order(candidates)` | ○ |
| C-130 | ExperimentFinder.execute | E-28: `def execute; relation` | ○ |
| C-131 | ExperimentFinder with_candidate_count | E-28: `def with_candidate_count` | ○ |
| C-132 | ExperimentFinder ソート | E-28: `def ordered` | ○ |
| C-133 | ModelFinder.execute | E-29: `def execute; relation` | ○ |
| C-134 | ModelFinder nameフィルタ | E-29: `def by_name` | ○ |
| C-135 | ModelFinder ソート | E-29: `def ordered` | ○ |
| C-136 | ModelFinder.count | E-29: `def count; relation.length` | ○ |
| C-137 | ModelVersionFinder.execute | E-30: `def execute; relation` | ○ |
| C-138 | ModelVersionFinder versionフィルタ | E-30: `def by_version` | ○ |
| C-139 | ModelVersionFinder ソート | E-30: `def ordered` | ○ |

## 4) 不足情報（Unknown / Missing）
- なし（全てのテストケースはソースコードから直接抽出）

## 5) リスクフラグ（レビュー観点）
- 0: 低リスク - 全てのテストケースがソースコードに基づいて生成されている
- 注意点：
  - バリデーションメッセージの詳細は実装確認が必要
  - 外部依存（Packages::MlModel::Package等）のモック方針は別途検討が必要
  - トランザクション処理のロールバックテストは統合テスト環境での確認が推奨される

## 6) レビュアーチェックリスト（最小）
- [ ] モデルの全リレーション（belongs_to/has_many/has_one）がテストケースでカバーされているか
- [ ] バリデーション（presence/length/uniqueness/format）が正常系・異常系・境界値でカバーされているか
- [ ] カスタムバリデーション（valid_default_experiment?等）がカバーされているか
- [ ] before_destroyコールバックの動作がカバーされているか
- [ ] scope（latest, by_name等）がカバーされているか
- [ ] クラスメソッド（by_project_id_and_*等）がカバーされているか
- [ ] サービスクラスの正常系・異常系がカバーされているか
- [ ] トランザクション処理（CreateModelService等）のロールバックがカバーされているか
- [ ] Finderのフィルタリング・ソート機能がカバーされているか
- [ ] 監査ログ（audit_creation_event等）の記録がカバーされているか
