<!-- task=proto_restructure plan=0 tag=PROTO_MOVE -->

# Proto 루트 디렉터리 독립화

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

각 항목의 체크리스트를 완료하면서 `[ ]`를 `[x]`로 표시하라.
중간 검증 명령은 해당 항목 구현 직후 실행하고, 출력을 `CODE_REVIEW.md`의 검증 결과 섹션에 붙여넣어라.
최종 검증도 마찬가지로 실행 후 출력을 기록하라.
계획과 다르게 구현한 부분은 이유와 함께 `CODE_REVIEW.md`의 "계획 대비 변경 사항"에 기록하라.

⚠️ **이 태스크는 모든 언어의 빌드 경로를 변경한다. 각 검증을 반드시 실행한 후 다음 단계로 넘어가라.**

---

## 배경

현재 proto canonical source가 `dart/lib/src/packets/message_common.proto`에 위치한다.
Dart는 5개 언어 구현체 중 하나이지만 동시에 스펙 원본의 저장소 역할을 하고 있어,
새 기여자에게 "proto = Dart 전용"으로 오해될 수 있다.
`proto/message_common.proto` 루트 디렉터리로 이동하면:

- proto가 특정 언어 종속성 없이 독립 소스임이 명확해진다
- 새 언어 포팅 시 proto 위치가 자명해진다
- `check_proto_sync.sh`의 "canonical Dart proto"라는 명칭이 사라진다

## 언어별 proto 현황

| 언어 | 현재 위치 | 방식 | 변경 여부 |
|------|----------|------|---------|
| Dart | `dart/lib/src/packets/message_common.proto` (canonical) | `protoc --dart_out` (generate_proto.sh) | 제거 후 생성 경로 변경 |
| Go | `go/packets/message_common.proto` (go_package 옵션 포함 복사본) | `protoc --go_out` (generate_proto.sh) | 유지 (언어 옵션 필요), sync 비교 대상 변경 |
| Kotlin | `kotlin/src/main/proto/message_common.proto` (java 옵션 포함 복사본) | Gradle protobuf 플러그인 | 유지 (언어 옵션 필요), sync 비교 대상 변경 |
| TypeScript | `typescript/src/packets/message_common_pb.ts` (생성 결과물만, .proto 없음) | `protoc-gen-es` 수동 실행 | 영향 없음 |
| Python | `python/toki_socket/packets/message_common_pb2.py` (생성 결과물만, .proto 없음) | `protoc --python_out` 수동 실행 | 영향 없음 |

## 의존 관계 및 구현 순서

```
[PROTO_MOVE-1] proto/ 생성 + generate_proto.sh 수정
→ [PROTO_MOVE-2] check_proto_sync.sh canonical 경로 변경
→ [PROTO_MOVE-3] PROTOCOL.md 업데이트
→ [PROTO_MOVE-4] dart/lib/src/packets/message_common.proto 제거
```

---

### [PROTO_MOVE-1] `proto/` 디렉터리 생성 및 generate_proto.sh 수정

**문제**

`tools/generate_proto.sh`가 Dart canonical에서 직접 생성한다.

```bash
# 현재
cd "$repo_root/dart"
protoc --dart_out=lib/src/packets lib/src/packets/message_common.proto

cd "$repo_root/go"
protoc --go_out=. --go_opt=paths=source_relative packets/message_common.proto
```

**해결 방법**

1. `proto/message_common.proto` 생성: `dart/lib/src/packets/message_common.proto`에서 언어 옵션 없이 그대로 복사 (현재 Dart canonical에는 언어 옵션이 없으므로 내용 동일).
2. `generate_proto.sh`의 Dart 생성 경로를 `proto/`에서 `dart/lib/src/packets/`로 출력하도록 변경.
3. Go 생성은 Go copy(`go/packets/message_common.proto`)에서 그대로 진행 (go_package 옵션 보존 필요).

Before (`generate_proto.sh` Dart 섹션):
```bash
(
  cd "$repo_root/dart"
  protoc --dart_out=lib/src/packets lib/src/packets/message_common.proto
)
```

After:
```bash
(
  protoc \
    --proto_path="$repo_root/proto" \
    --dart_out="$repo_root/dart/lib/src/packets" \
    message_common.proto
)
```

Go 섹션은 변경 없음 (Go는 자체 복사본에서 생성).

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

- [x] `proto/message_common.proto` 생성 (dart canonical과 동일 내용)
- [x] `tools/generate_proto.sh` — Dart 생성 섹션 경로 변경

**테스트 없음** — generate_proto.sh 실행으로 검증

**중간 검증**

```bash
# protoc가 있는 환경에서 실행
tools/generate_proto.sh
# 오류 없이 완료

# 생성 결과가 기존과 동일한지 확인
cd dart && dart analyze
# No issues found
```

---

### [PROTO_MOVE-2] `check_proto_sync.sh` canonical 경로 변경

**문제**

`tools/check_proto_sync.sh`의 canonical이 `dart_proto` 변수로 Dart 경로를 가리킨다.

```bash
dart_proto="$repo_root/dart/lib/src/packets/message_common.proto"
```

**해결 방법**

변수명과 경로를 `proto/` 기준으로 변경한다.

Before:
```bash
dart_proto="$repo_root/dart/lib/src/packets/message_common.proto"
go_proto="$repo_root/go/packets/message_common.proto"
kotlin_proto="$repo_root/kotlin/src/main/proto/message_common.proto"

if [[ ! -f "$dart_proto" ]]; then
  echo "Missing canonical Dart proto: $dart_proto" >&2
  exit 1
fi
# ...
normalize_proto "$dart_proto" >"$tmp_dir/dart.proto"
normalize_proto "$go_proto" >"$tmp_dir/go.proto"
# ...
if ! cmp -s "$tmp_dir/dart.proto" "$tmp_dir/go.proto"; then
  echo "Proto schema mismatch: go/packets/message_common.proto must match the Dart canonical proto ..."
# ...
```

After:
```bash
canonical_proto="$repo_root/proto/message_common.proto"
go_proto="$repo_root/go/packets/message_common.proto"
kotlin_proto="$repo_root/kotlin/src/main/proto/message_common.proto"

if [[ ! -f "$canonical_proto" ]]; then
  echo "Missing canonical proto: $canonical_proto" >&2
  exit 1
fi
# ...
normalize_proto "$canonical_proto" >"$tmp_dir/canonical.proto"
normalize_proto "$go_proto" >"$tmp_dir/go.proto"
# ...
if ! cmp -s "$tmp_dir/canonical.proto" "$tmp_dir/go.proto"; then
  echo "Proto schema mismatch: go/packets/message_common.proto must match proto/message_common.proto ..."
# ...
```

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

- [x] `tools/check_proto_sync.sh` — `dart_proto` → `canonical_proto`, 경로를 `proto/message_common.proto`로 변경
- [x] `tools/check_proto_sync.sh` — 오류 메시지에서 "Dart canonical" 문구 제거
- [x] `tools/check_proto_sync.sh` — normalize 비교 대상 변수명 일관성 수정

**중간 검증**

```bash
tools/check_proto_sync.sh
# Proto schemas are in sync.
```

---

### [PROTO_MOVE-3] `PROTOCOL.md` Proto Source 섹션 업데이트

**문제**

`PROTOCOL.md` 하단 "Proto Source" 섹션이 Dart 경로를 canonical로 명시한다.

```markdown
`dart/lib/src/packets/message_common.proto` is the canonical packet definition.
All language implementations must keep the same message schema and generate bindings from it.
```

**해결 방법**

```markdown
`proto/message_common.proto` is the canonical packet definition.
All language implementations generate bindings from it.
Language-specific generation options (go_package, java_package, etc.) are kept in each
language's own proto copy under `go/packets/` and `kotlin/src/main/proto/`.
```

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

- [x] `PROTOCOL.md` — "Proto Source" 섹션 경로 및 설명 업데이트

**테스트 없음** — 문서 전용

**중간 검증**

```bash
grep "canonical" PROTOCOL.md
# proto/message_common.proto 언급
grep "dart/lib/src/packets/message_common.proto" PROTOCOL.md
# 출력 없음이 정상
```

---

### [PROTO_MOVE-4] `dart/lib/src/packets/message_common.proto` 제거

**문제**

PROTO_MOVE-1~3 완료 후 `dart/lib/src/packets/message_common.proto`는 더 이상 canonical이 아니다.
그러나 여전히 파일로 남아 혼란을 줄 수 있다.

**해결 방법**

파일을 삭제한다. Dart 생성 결과물인 `.pb.dart` 파일들은 유지한다.

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

- [x] `dart/lib/src/packets/message_common.proto` 삭제
- [x] `dart analyze` — proto 파일 제거 후 여전히 No issues인지 확인

**중간 검증**

```bash
ls dart/lib/src/packets/
# message_common.pb.dart, message_common.pbenum.dart 등 생성 결과물만 존재
# message_common.proto 없음

cd dart && dart analyze
# No issues found
cd dart && dart test
# 전체 PASS
```

---

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `proto/message_common.proto` (신규) | PROTO_MOVE-1 |
| `tools/generate_proto.sh` | PROTO_MOVE-1 |
| `tools/check_proto_sync.sh` | PROTO_MOVE-2 |
| `PROTOCOL.md` | PROTO_MOVE-3 |
| `dart/lib/src/packets/message_common.proto` (삭제) | PROTO_MOVE-4 |

## 최종 검증

```bash
# proto sync 도구 검증
tools/check_proto_sync.sh
# Proto schemas are in sync.

# Dart
cd dart && dart analyze
# No issues found
cd dart && dart test
# 전체 PASS

# Go
cd go && go build ./...
# 빌드 성공

# Kotlin
cd kotlin && env JAVA_HOME=/config/opt/jdk/jdk-17.0.10+7 GRADLE_USER_HOME=/tmp/gradle ./gradlew build
# BUILD SUCCESSFUL

# proto/ 파일 확인
ls proto/
# message_common.proto 존재
ls dart/lib/src/packets/
# *.pb.dart만 존재, message_common.proto 없음
```
