<!-- task=03_command_catalog_samples plan=1 tag=REVIEW_REVIEW_SAMPLE -->

# Command Catalog Sample Coverage Follow-up

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

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

## 배경

1차 구현은 주요 samplePath 연결과 iOS 샘플 필드명 정리는 진행했지만, 코드리뷰에서 세 가지 Required 문제가 확인되었다.

- GitHub PR 샘플의 결과 저장 필드가 write tag가 아닌 read tag를 사용한다.
- stale iOS field 회귀 테스트가 실제 stale key를 탐지하지 못한다.
- 계획에서 요구한 samplePath null 정책 테스트 또는 allowlist가 추가되지 않았다.

## 분석 결과

### 읽은 파일

- `agent-task/03_command_catalog_samples/code_review_local_G05_0.log`
- `agent-task/03_command_catalog_samples/plan_local_G05_0.log`
- `assets/yaml/sample/09_network.yaml`
- `test/oto_command_catalog_test.dart`
- `lib/oto/core/tag_system.dart`
- `lib/oto/commands/git/git_hub.dart`

### 범위 결정 근거

후속 작업은 리뷰 Required 항목만 다룬다. 커맨드 실행 로직과 데이터 모델 변경은 제외하고, 샘플 YAML과 catalog 테스트만 수정한다.

### 빌드 등급

build=`local-G05`, review=`local-G05`: 정적 샘플/테스트 수정이며 터미널 상호작용이나 외부 CLI 동작 판단이 필요하지 않다.

## 구현 체크리스트

- [ ] [REVIEW_REVIEW_SAMPLE-1] GitHub PR 샘플의 결과 저장 필드를 write tag로 수정한다.
- [ ] [REVIEW_REVIEW_SAMPLE-2] stale iOS field 회귀 테스트가 실제 stale key를 탐지하도록 고친다.
- [ ] [REVIEW_REVIEW_SAMPLE-3] samplePath null 정책 테스트 또는 명시적 allowlist를 추가한다.
- [ ] 중간 검증과 최종 검증 명령을 실행하고 결과를 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_SAMPLE-1] GitHub write tag 수정

문제: [09_network.yaml](/config/workspace/oto/assets/yaml/sample/09_network.yaml:105)의 `setURL`, [09_network.yaml](/config/workspace/oto/assets/yaml/sample/09_network.yaml:106)의 `setNumber`, [09_network.yaml](/config/workspace/oto/assets/yaml/sample/09_network.yaml:118)의 `setValue`가 read tag인 `<!property...>`를 사용한다. `GitHubPullRequestCreate`와 `GitHubPullRequestList`는 이 값을 `setProperty()`에 넘기므로 `<@property...>` write tag가 필요하다.

해결 방법:

```yaml
setURL: <@property.prURL>
setNumber: <@property.prNumber>
setValue: <@property.openPRs>
```

수정 파일 및 체크리스트:

- [ ] `assets/yaml/sample/09_network.yaml`: GitHub PR create/list 결과 저장 필드를 write tag로 변경.
- [ ] 기존 HTTP/FTP 샘플의 read/write tag 구조는 변경하지 않는다.

테스트 작성: 기존 catalog 테스트가 command containment를 유지한다. 가능하면 write-tag 회귀 테스트를 sample test에 추가한다.

중간 검증:

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

기대 결과: All tests passed.

### [REVIEW_REVIEW_SAMPLE-2] stale field 테스트 실효성 복구

문제: [oto_command_catalog_test.dart](/config/workspace/oto/test/oto_command_catalog_test.dart:122), [oto_command_catalog_test.dart](/config/workspace/oto/test/oto_command_catalog_test.dart:142), [oto_command_catalog_test.dart](/config/workspace/oto/test/oto_command_catalog_test.dart:170)의 정규식은 `^`를 전체 문자열에 적용하면서 `multiLine: true`를 주지 않아 첫 줄 외 위치의 stale key를 잡지 못한다.

해결 방법: 각 stale key 검사를 줄 단위로 수행하거나 `RegExp(..., multiLine: true)`를 사용한다. TestFlight 검사는 comment line을 제외한 command block 또는 전체 non-comment line에서 `username:`/`password:` YAML key를 확인한다.

수정 파일 및 체크리스트:

- [ ] `test/oto_command_catalog_test.dart`: `workspacePath` stale key 검사가 실제 YAML 라인을 탐지하도록 수정.
- [ ] `test/oto_command_catalog_test.dart`: `exportOptionsPlist` stale key 검사가 실제 YAML 라인을 탐지하도록 수정.
- [ ] `test/oto_command_catalog_test.dart`: TestFlight `username`/`password` stale key 검사가 comment line에 의존하지 않고 실제 param key만 확인하도록 수정.

테스트 작성: 작성. 임시로 stale key를 넣으면 실패할 정도로 assertion이 의미 있어야 한다. 임시 변경은 남기지 않는다.

중간 검증:

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

기대 결과: All tests passed.

### [REVIEW_REVIEW_SAMPLE-3] samplePath null 정책 테스트

문제: [oto_command_catalog_test.dart](/config/workspace/oto/test/oto_command_catalog_test.dart:43)는 `samplePath == null`이면 건너뛴다. 기존 계획은 missing samplePath allowlist 또는 all-public rule을 요구했으므로, 새 공개 커맨드가 샘플 없이 등록되는 회귀를 막지 못한다.

해결 방법: 둘 중 하나를 선택한다.

1. 모든 공개 YAML 커맨드에 `samplePath`를 요구하는 테스트를 추가한다.
2. 샘플이 의도적으로 없는 내부/특수 커맨드 allowlist를 테스트에 명시하고, allowlist 외 registered spec은 `samplePath` non-null을 요구한다.

현재 repo에는 samplePath가 없는 등록 커맨드가 다수 남아 있으므로, 무조건 all-public rule을 적용하기 어렵다면 allowlist와 사유를 테스트 이름/주석에 고정한다.

수정 파일 및 체크리스트:

- [ ] `test/oto_command_catalog_test.dart`: samplePath null 정책 테스트를 추가한다.
- [ ] allowlist를 선택하면 각 항목을 고정 목록으로 두고, 이번 태스크에서 샘플을 연결한 iOS/Git/GitHub 계열이 allowlist에 들어가지 않도록 한다.

테스트 작성: 작성.

중간 검증:

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

기대 결과: All tests passed.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `assets/yaml/sample/09_network.yaml` | REVIEW_REVIEW_SAMPLE-1 |
| `test/oto_command_catalog_test.dart` | REVIEW_REVIEW_SAMPLE-2, REVIEW_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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
