<!-- task=05_git_split plan=0 tag=REFACTOR -->

# Git Command Split

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

**경고: 구현 완료의 마지막 단계는 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 모두 채우는 것이다.**
구현 체크리스트를 기준으로 작업하고, plan과 review stub 양쪽의 체크리스트를 완료하며, 중간/최종 검증을 실행한 실제 출력으로 `CODE_REVIEW-*-G??.md`를 채운다.
리뷰 파일의 `이 파일을 읽는 리뷰 에이전트에게` 섹션에 있는 아카이브 지시는 실행하지 말고, `코드리뷰 전용 체크리스트`는 수정하거나 체크하지 않는다.

## 배경

`git.dart`는 원격 sync, commit, checkout, revision 조회, reset, stash, branch report를 한 파일에 담고 있다.
일부 command는 `git reset --hard`와 `git clean`처럼 파괴적 동작을 포함하므로 AI가 변경 범위를 더 작게 읽을 수 있어야 한다.
이 작업은 `lib/oto/commands/git/git.dart` import 호환과 `registerGitCommands()`를 유지하면서 책임별 파일로 분리한다.

## 의존 관계 및 구현 순서

- 선행 task 없음. `agent-task/05_git_split`은 git command 내부 파일 분리이며 독립적으로 시작할 수 있다.
- `agent-task/03+execution_context_boundaries`와 동시에 구현 중이면 `Command` base 변경 사항을 merge한 뒤 runtime 테스트를 다시 실행한다.

## 분석 결과

### 읽은 파일

- `lib/oto/commands/git/git.dart`
- `lib/oto/data/git_data.dart`
- `assets/yaml/sample/06_git.yaml`
- `test/oto_command_runtime_test.dart`
- `test/oto_command_catalog_test.dart`
- `README.md`
- `agent-ops/rules/project/domain/command/rules.md`
- `agent-ops/rules/project/domain/sample/rules.md`

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

- `test/oto_command_runtime_test.dart:104`는 `Git` command shell buffer delegation만 커버한다.
- `GitCommit`, `GitPull`, `GitPush`, `GitCheckout`, `GitReset`, `GitStash*`, `GitBranch` shell buffer와 destructive behavior는 기존 테스트가 없다.
- 신규 유닛 테스트는 사용자 요청 범위 밖이므로 작성하지 않고, 기존 runtime/catalog 테스트로 import와 registration 회귀를 확인한다.

### 심볼 참조

- renamed/removed symbol: none.
- `registerGitCommands()` call site: `lib/oto/commands/command_registry.dart:65`.
- `Git` test import: `test/oto_command_runtime_test.dart:9`.
- `Git` class group: `Git` at `git.dart:10`, `GitCommit` at `git.dart:29`, `GitCheckout` at `git.dart:90`, `GitBranch` at `git.dart:241`, `registerGitCommands()` at `git.dart:290`.

### 범위 결정 근거

- `lib/oto/data/git_data.dart` data model은 변경하지 않는다.
- GitHub command 파일 `lib/oto/commands/git/git_hub.dart`는 제외한다. GitHub API/CLI 명령은 별도 책임이고 현재 파일 크기 문제가 덜하다.
- destructive git command 동작 개선은 제외한다. 이번 작업은 class 이동과 import 유지에 한정한다.

### 빌드 등급

- build lane: `cloud-G07`. git shell command와 destructive command가 포함되고 실제 git repository 통합 테스트는 약하다.

## 구현 체크리스트

- [ ] generic/remote Git command를 책임별 파일로 분리한다.
- [ ] revision/reset command를 별도 파일로 분리한다.
- [ ] stash/branch command를 별도 파일로 분리한다.
- [ ] `git.dart` import 호환과 `registerGitCommands()` public 진입점을 유지한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REFACTOR-1] Generic and remote Git commands split

#### 문제

`Git`, `GitCommit`, `GitPull`, `GitPush`, `GitCheckout`가 `lib/oto/commands/git/git.dart:10`부터 `122`에 함께 있다.
원격 branch 조작과 commit 동작을 수정할 때 전체 git 파일을 읽어야 한다.

Before (`lib/oto/commands/git/git.dart:10`):

```dart
class Git extends Command {
  @override
  Future execute(DataCommand command) async {
```

#### 해결 방법

새 파일 `lib/oto/commands/git/git_remote.dart`를 만들고 generic/commit/pull/push/checkout command를 이동한다.
`git.dart`는 export와 registration 중심 파일로 유지한다.

After:

```dart
// git.dart
export 'git_remote.dart';
export 'git_revision.dart';
export 'git_stash.dart';
export 'git_branch.dart';

void registerGitCommands() { ... }
```

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

- [ ] `lib/oto/commands/git/git_remote.dart`: `Git`, `GitCommit`, `GitPull`, `GitPush`, `GitCheckout` 이동.
- [ ] `lib/oto/commands/git/git.dart`: export와 registration 유지.
- [ ] `test/oto_command_runtime_test.dart`: 기존 `import 'package:oto/oto/commands/git/git.dart';`가 계속 동작하는지 확인.

#### 테스트 작성

- 신규 유닛 테스트는 작성하지 않는다. 기존 runtime 테스트가 `Git` import/execute를 간접 검증한다.

#### 중간 검증

```bash
dart test test/oto_command_runtime_test.dart
```

기대 결과: `git command delegates command buffer to runtime` 테스트가 통과한다.

### [REFACTOR-2] Revision and reset commands split

#### 문제

`GitCount`, `GitRev`, `GitReset`은 `lib/oto/commands/git/git.dart:125`부터 `171`에 있으며 stdout parsing과 destructive cleanup command를 섞고 있다.
조회성 command와 파괴적 reset command가 큰 파일 중간에 묻혀 있다.

Before (`lib/oto/commands/git/git.dart:125`):

```dart
class GitCount extends Command {
  @override
  Future execute(DataCommand command) async {
```

#### 해결 방법

새 파일 `lib/oto/commands/git/git_revision.dart`를 만들고 `GitCount`, `GitRev`, `GitReset`을 이동한다.
shell 문자열은 그대로 이동하고 동작 변경을 하지 않는다.

After:

```dart
// git_revision.dart
class GitCount extends Command { ... }
class GitRev extends Command { ... }
class GitReset extends Command { ... }
```

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

- [ ] `lib/oto/commands/git/git_revision.dart`: revision/reset command 이동.
- [ ] `lib/oto/commands/git/git.dart`: registration에서 이동된 class 참조 유지.

#### 테스트 작성

- 신규 유닛 테스트는 작성하지 않는다. destructive reset behavior는 별도 테스트 설계가 필요하다.

#### 중간 검증

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

기대 결과: GitRev/GitCount/GitReset registration spec 검증이 통과한다.

### [REFACTOR-3] Stash and branch commands split

#### 문제

`GitStashPush`, `GitStashApply`, `GitBranch`는 `lib/oto/commands/git/git.dart:175`부터 `288`에 있으며 stash parsing, branch JSON file 생성, jq 의존 command를 함께 포함한다.
AI가 branch report만 수정해도 stash logic을 같이 읽게 된다.

Before (`lib/oto/commands/git/git.dart:175`):

```dart
class GitStashPush extends Command {
  @override
  Future execute(DataCommand command) async {
```

#### 해결 방법

`GitStashPush`/`GitStashApply`를 `git_stash.dart`, `GitBranch`를 `git_branch.dart`로 이동한다.
`BranchInfo` data model은 `lib/oto/data/git_data.dart`에 그대로 둔다.

After:

```dart
// git_stash.dart
class GitStashPush extends Command { ... }
class GitStashApply extends Command { ... }

// git_branch.dart
class GitBranch extends Command { ... }
```

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

- [ ] `lib/oto/commands/git/git_stash.dart`: stash command 이동.
- [ ] `lib/oto/commands/git/git_branch.dart`: branch command 이동.
- [ ] `lib/oto/commands/git/git.dart`: export와 registration 유지.

#### 테스트 작성

- 신규 유닛 테스트는 작성하지 않는다. stash/branch shell behavior는 별도 runtime 테스트 확장 대상이다.

#### 중간 검증

```bash
rg --sort path -n "class Git|class GitCommit|class GitRev|class GitReset|class GitStashPush|class GitBranch|void registerGitCommands" lib/oto/commands/git
```

기대 결과: 각 class가 책임별 파일에 있고 `registerGitCommands`는 유지된다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/oto/commands/git/git.dart` | REFACTOR-1, REFACTOR-2, REFACTOR-3 |
| `lib/oto/commands/git/git_remote.dart` | REFACTOR-1 |
| `lib/oto/commands/git/git_revision.dart` | REFACTOR-2 |
| `lib/oto/commands/git/git_stash.dart` | REFACTOR-3 |
| `lib/oto/commands/git/git_branch.dart` | REFACTOR-3 |
| `test/oto_command_runtime_test.dart` | REFACTOR-1 검증 대상 |
| `test/oto_command_catalog_test.dart` | REFACTOR-2 검증 대상 |

## 최종 검증

```bash
dart format lib/oto/commands/git/git.dart lib/oto/commands/git/git_remote.dart lib/oto/commands/git/git_revision.dart lib/oto/commands/git/git_stash.dart lib/oto/commands/git/git_branch.dart
dart analyze
dart test test/oto_command_runtime_test.dart test/oto_command_catalog_test.dart
rg --sort path -n "class Git|class GitCommit|class GitRev|class GitReset|class GitStashPush|class GitBranch|void registerGitCommands" lib/oto/commands/git
```

기대 결과: format/analyze/test가 통과하고, 검색 결과가 책임별 파일 분리를 보여준다.

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