<!-- task=01+04_command_catalog plan=0 tag=REFACTOR -->

# Command Catalog Plan

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

**필수 경고: 구현 마지막 단계에서 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 모두 채워야 한다. 이 파일이 채워지기 전에는 작업이 완료된 것이 아니다.**
구현 체크리스트와 검증 명령을 그대로 수행하고 실제 출력을 review stub에 기록한다.
review 파일의 아카이브 지시와 `코드리뷰 전용 체크리스트`는 리뷰 에이전트 전용이다.

## 배경

커맨드 추가/수정 시 `CommandType`, 구현체, 데이터 모델, 샘플 YAML의 관계가 수동 지식에 의존한다.
AI-first 작업을 위해 command registry에 최소 메타데이터를 부여하고 누락을 테스트로 잡는다.

## 분석 결과

### 읽은 파일

- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/rules/project/domain/command/rules.md`
- `agent-ops/rules/project/domain/sample/rules.md`
- `lib/oto/commands/command.dart`
- `lib/oto/commands/command_registry.dart`
- `lib/oto/data/command_data.dart`
- `pubspec.yaml`

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

- 모든 `CommandType`이 등록되는지 검증하는 테스트 없음.
- 등록된 command가 category/dataModel/sample metadata를 갖는지 검증하는 테스트 없음.
- sample path가 실제 존재하는지 검증하는 테스트 없음.

### 심볼 참조

- rename/remove 예정 심볼: none.
- `Command.register(` call sites: `lib/oto/commands/command_registry.dart:42` 및 각 command category register 함수 전체.

### 범위 결정 근거

- 이 task는 command catalog metadata와 tests만 다룬다.
- YAML schema 생성, README 자동 생성, 샘플 전체 검증기는 후속 task로 남긴다.
- 기존 command enum 이름은 변경하지 않는다.

### 빌드 등급

- build lane: `local-G06` — registry metadata 추가와 테스트 중심의 내부 리팩토링이다.
- review lane: `cloud-G06` — command 등록 누락과 샘플 경로 검증 범위가 넓다.

## 구현 체크리스트

- [ ] [REFACTOR-1] `CommandSpec` 카탈로그를 추가하고 등록 누락 검증을 만든다.
- [ ] 모든 중간 검증과 최종 검증을 실행하고 실제 출력을 `CODE_REVIEW-*-G??.md`에 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- `agent-task/01_test_baseline/complete.log`가 있어야 시작한다.
- `agent-task/01+02_runtime_context/complete.log`가 있어야 시작한다.
- 이 task는 `01+03_command_io_ports`와 병렬 가능하다.

### [REFACTOR-1] CommandSpec 카탈로그 도입

#### 문제

`registerAllCommands()`는 factory 등록만 수행하고, AI가 command 추가/수정 시 확인할 metadata가 없다.

```dart
// lib/oto/commands/command_registry.dart:41
void registerAllCommands() {
  Command.register(CommandType.SimpleCommand, () => SimpleCommand());
  ...
}
```

#### 해결 방법

`CommandSpec`을 추가하고 `Command.register()`가 optional spec을 받게 한다.
테스트에서는 `CommandType.values` 전체가 등록되고 spec을 갖는지 확인한다.

```dart
class CommandSpec {
  final CommandType type;
  final String category;
  final String dataModel;
  final String? samplePath;
}
```

#### 수정 파일 및 체크리스트

- [ ] `lib/oto/commands/command.dart`에 `CommandSpec`, spec registry getter 추가
- [ ] `lib/oto/commands/command_registry.dart`와 category register 함수에 spec 부여
- [ ] samplePath는 실제 존재하는 `assets/yaml/sample/**`만 지정
- [ ] 등록 누락과 spec 누락을 잡는 테스트 추가

#### 테스트 작성

- 작성: `test/oto_command_catalog_test.dart`
- 테스트명: `all command types are registered`, `all registered commands expose specs`, `spec sample paths exist when provided`
- 목적: command 추가/수정 시 enum/registry/sample 누락을 잡는다.

#### 중간 검증

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

예상: command catalog 테스트 통과.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/oto/commands/command.dart` | REFACTOR-1 |
| `lib/oto/commands/command_registry.dart` | REFACTOR-1 |
| `lib/oto/commands/**` | REFACTOR-1 |
| `test/oto_command_catalog_test.dart` | REFACTOR-1 |

## 최종 검증

```bash
dart analyze
```

예상: `No issues found!`

```bash
dart test
```

예상: 모든 테스트 통과.

```bash
rg --sort path -n "Command\\.register\\(" lib/oto/commands
```

예상: 모든 등록 call이 spec을 제공하거나 spec helper를 통해 등록된다.

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