<!-- task=03_command_catalog_samples plan=0 tag=REVIEW_SAMPLE -->

# Command Catalog Sample Coverage

## 이 파일을 읽는 구현 에이전트에게

**구현의 마지막 단계는 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채우는 것이다. 이 파일이 채워지기 전에는 작업이 완료된 것이 아니다.** 구현 체크리스트를 기준으로 작업하고, 중간/최종 검증을 실행한 뒤 실제 구현 내용과 stdout/stderr를 review stub에 기록한다. review 파일의 archive/complete.log 지시는 코드리뷰 스킬 전용이며 구현 에이전트가 실행하거나 `코드리뷰 전용 체크리스트`를 수정하면 안 된다.

## 배경

AI-first YAML 작성은 `CommandSpec`와 `assets/yaml/sample/**`를 신뢰할 수 있어야 한다. 현재 일부 공개 커맨드는 `samplePath`가 없고, iOS 샘플에는 실제 데이터 모델과 다른 필드명이 남아 있다. 샘플을 단일 참조점으로 만들기 위한 보강이 필요하다.

## 분석 결과

### 읽은 파일

- `lib/oto/commands/command.dart`
- `lib/oto/commands/command_registry.dart`
- `lib/oto/commands/build/build_ios.dart`
- `lib/oto/commands/git/git.dart`
- `lib/oto/commands/git/git_hub.dart`
- `lib/oto/data/build_data.dart`
- `lib/oto/data/git_data.dart`
- `lib/oto/data/network_data.dart`
- `assets/yaml/sample/06_git.yaml`
- `assets/yaml/sample/09_network.yaml`
- `assets/yaml/sample/10_build_ios.yaml`
- `assets/yaml/sample/12_scheduler.yaml`
- `test/oto_command_catalog_test.dart`

### 테스트 커버리지 공백

- `CommandSpec.samplePath`는 존재/포함만 검사하고, 공개 커맨드가 samplePath를 의도적으로 갖는지 여부는 강제하지 않는다.
- iOS 샘플의 param field가 `DataBuildiOS`, `DataArchiveiOS`, `DataExportiOS`, `DataTestflight*`와 맞는지 확인하는 테스트가 없다.

### 심볼 참조

- renamed/removed symbols: none.

### 분할 판단

분할 정책을 먼저 평가했다. 이 task는 sample/catalog 문서화 경계만 다룬다. `01_command_runtime_contract`, `02_pipeline_yaml_validation`와 런타임 의존성이 없고 독립 검증 가능하므로 `03_` 독립 디렉터리로 둔다.

### 범위 결정 근거

이 작업은 `CommandSpec.samplePath`, sample YAML, catalog tests만 수정한다. 커맨드 실행 로직과 데이터 모델 필드명 변경은 제외한다.

### 빌드 등급

build=`local-G05`, review=`local-G05`: 문서/샘플/테스트 보강 중심이며 실행 로직 영향은 없다.

## 구현 체크리스트

- [ ] [REVIEW_SAMPLE-1] 공개 커맨드의 `samplePath` 누락 여부를 결정하고 필요한 샘플을 연결한다.
- [ ] [REVIEW_SAMPLE-2] iOS/GitHub/Git 샘플을 실제 데이터 모델 필드명과 맞춘다.
- [ ] [REVIEW_SAMPLE-3] catalog/sample 테스트를 강화한다.
- [ ] 중간 검증과 최종 검증 명령을 실행하고 결과를 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_SAMPLE-1] samplePath 누락 정리

문제: [build_ios.dart](/config/workspace/oto/lib/oto/commands/build/build_ios.dart:42)의 CodeSign 계열, [git.dart](/config/workspace/oto/lib/oto/commands/git/git.dart:34)의 GitPull, [git.dart](/config/workspace/oto/lib/oto/commands/git/git.dart:83)의 GitReset/Stash 계열, [git_hub.dart](/config/workspace/oto/lib/oto/commands/git/git_hub.dart:125)의 GitHub 계열은 samplePath가 없다.

해결 방법: 공개 YAML 커맨드는 관련 samplePath를 추가한다. 내부 전용으로 남길 커맨드가 있다면 테스트의 allowlist에 이유를 명시한다.

Before:

```dart
// lib/oto/commands/git/git.dart:37
spec: const CommandSpec(
  type: CommandType.GitPull,
  category: 'git',
  dataModel: 'DataGitPull',
),
```

After:

```dart
spec: const CommandSpec(
  type: CommandType.GitPull,
  category: 'git',
  dataModel: 'DataGitPull',
  samplePath: 'assets/yaml/sample/06_git.yaml',
),
```

수정 파일 및 체크리스트:

- [ ] `lib/oto/commands/build/build_ios.dart`: CodeSign 계열 samplePath 판단/추가.
- [ ] `lib/oto/commands/git/git.dart`: GitPull/GitReset/Stash samplePath 판단/추가.
- [ ] `lib/oto/commands/git/git_hub.dart`: GitHub 계열 samplePath 판단/추가.

테스트 작성: 작성. samplePath 누락 테스트를 추가하되, 의도적 internal allowlist는 이유와 함께 고정한다.

중간 검증:

```bash
dart test test/oto_command_catalog_test.dart
```

기대 결과: All tests passed.

### [REVIEW_SAMPLE-2] 샘플 필드명 동기화

문제: [10_build_ios.yaml](/config/workspace/oto/assets/yaml/sample/10_build_ios.yaml:33)의 `workspacePath`, [10_build_ios.yaml](/config/workspace/oto/assets/yaml/sample/10_build_ios.yaml:47)의 `exportOptionsPlist`, [10_build_ios.yaml](/config/workspace/oto/assets/yaml/sample/10_build_ios.yaml:54)의 TestFlight username/password 필드는 [build_data.dart](/config/workspace/oto/lib/oto/data/build_data.dart:88)의 실제 모델과 맞지 않는다.

해결 방법: 모델 기준으로 샘플을 갱신한다. `BuildiOS`/`ArchiveiOS`는 `xcworkspaceFilePath` 또는 `xcodeProjectFilePath`, `ExportiOS`는 `exportOptionPlistPath`, TestFlight 계열은 `apiKeyPath`, `appID`, `version`, `buildNumber` 중심으로 정리한다.

수정 파일 및 체크리스트:

- [ ] `assets/yaml/sample/10_build_ios.yaml`: iOS build/archive/export 필드명 수정.
- [ ] `assets/yaml/sample/10_build_ios.yaml`: TestFlight 필드명 수정.
- [ ] `assets/yaml/sample/06_git.yaml`: GitPull/GitReset/GitStash 샘플 추가 여부 확인.
- [ ] 새 샘플에 실제 token/password를 넣지 않는다.

테스트 작성: 작성. 최소한 iOS 샘플의 command block이 실제 expected field name을 포함하고 stale field name을 포함하지 않는 테스트를 둔다.

중간 검증:

```bash
dart test test/oto_command_catalog_test.dart
```

기대 결과: All tests passed.

### [REVIEW_SAMPLE-3] catalog/sample 테스트 강화

문제: [oto_command_catalog_test.dart](/config/workspace/oto/test/oto_command_catalog_test.dart:33)는 sample file 존재와 command 포함만 확인한다. 존재하지 않는 param field를 막지 못한다.

해결 방법: 샘플 품질 테스트를 추가한다. 모든 non-internal CommandSpec에는 samplePath가 있고, samplePath가 지정된 커맨드는 해당 샘플에 command가 있으며, 알려진 stale field names가 없음을 검증한다.

수정 파일 및 체크리스트:

- [ ] `test/oto_command_catalog_test.dart`: missing samplePath allowlist 또는 all-public rule 추가.
- [ ] `test/oto_command_catalog_test.dart`: stale iOS field name regression 추가.
- [ ] `test/oto_command_catalog_test.dart`: samplePath command containment 기존 테스트 유지.

테스트 작성: 작성.

중간 검증:

```bash
dart test test/oto_command_catalog_test.dart
```

기대 결과: All tests passed.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/oto/commands/build/build_ios.dart` | REVIEW_SAMPLE-1 |
| `lib/oto/commands/git/git.dart` | REVIEW_SAMPLE-1 |
| `lib/oto/commands/git/git_hub.dart` | REVIEW_SAMPLE-1 |
| `assets/yaml/sample/10_build_ios.yaml` | REVIEW_SAMPLE-2 |
| `assets/yaml/sample/06_git.yaml` | REVIEW_SAMPLE-2 |
| `test/oto_command_catalog_test.dart` | REVIEW_SAMPLE-3 |

## 최종 검증

```bash
dart analyze
dart test test/oto_command_catalog_test.dart
dart test
```

기대 결과: `No issues found!`, catalog test pass, full test pass.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
