<!-- task=m-protocol-evolution-compatibility/02+01_legacy_alias plan=0 tag=ALIAS -->

# Plan - ALIAS

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

이 plan은 full-name foundation 완료 후 legacy simple-name 수신 alias를 모든 지원 언어의 parser/listener/request/pending response 경로에 일관되게 적용한다. 구현 후 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 내용으로 채운다. 사용자 결정이 필요한 blocker만 review stub의 `사용자 리뷰 요청`에 기록한다.

## 배경

마일스톤은 새 송신 기본값을 full proto name으로 바꾸되 기존 simple-name peer의 수신 호환성은 보존한다. 현재 Go/Kotlin/Python/TypeScript dispatch와 pending response 비교는 exact string lookup이므로 alias 규칙을 중앙화하지 않으면 parser만 통과하고 listener/request/response가 실패하는 부분 호환 상태가 된다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 질문은 금지이며, code-review가 `USER_REVIEW.md` 작성 여부를 판단한다.

## Roadmap Targets

- Milestone: `agent-roadmap/milestones/protocol-evolution-compatibility.md`
- Task ids:
  - `legacy-alias`: parser lookup, listener/request handler routing, response type matching, pending expected type 비교에 동일 alias 규칙 적용
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-test/local/rules.md`
- `agent-test/local/proto-socket-full-matrix.md`
- `agent-roadmap/milestones/protocol-evolution-compatibility.md`
- `dart/lib/src/communicator.dart`, `dart/test/communicator_test.dart`
- `go/communicator.go`, `go/test/communicator_test.go`
- `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`, `kotlin/src/test/kotlin/com/tokilabs/proto_socket/CommunicatorTest.kt`
- `python/proto_socket/communicator.py`, `python/test/test_communicator.py`
- `typescript/src/communicator.ts`, `typescript/test/communicator.test.ts`
- `PROTOCOL.md`, `VERSIONING.md`, `PORTING_GUIDE.md`

### 테스트 환경 규칙

`test_env=local`이다. 전체 protocol/API 호환성 변경이므로 최종 검증은 `bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all`이다. focused 중간 검증은 각 언어 unit test를 사용하되, 실행하지 못한 runtime은 명령과 차단 사유를 review stub에 기록한다.

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

- Dart에는 package-qualified receive 테스트가 있으나 canonical alias collision 검사는 없다.
- Go/Kotlin/Python/TypeScript는 simple alias receive, request handler alias, response alias, collision 초기화 실패 테스트가 부족하다.
- parser alias만 추가하면 `go/communicator.go:480-486`, `kotlin/.../Communicator.kt:421-427`, `python/.../communicator.py:519-524`, `typescript/src/communicator.ts:585-589`의 pending expected type 비교가 계속 실패한다.

### 심볼 참조

- 새 helper 후보: alias expansion/canonicalization helper per language.
- 변경 call site: parser map initialization, `AddListener`/`addListener`, `AddRequestListener`/`addRequestListener`, dispatch lookup, `_handle_response`/`handleResponse`, `parse`.

### 분할 판단

분할 정책을 평가했다. 이 plan은 `02+01_legacy_alias`이며 predecessor `01_proto_fullname_foundation`의 `complete.log`가 필요하다. 현재 작성 시점에는 predecessor가 missing이므로 구현 시작 전 `agent-task/m-protocol-evolution-compatibility/01_proto_fullname_foundation/complete.log` 또는 archive의 `01_*` complete.log를 확인해야 한다. 테스트 matrix 확장은 `03+01,02_fullname_tests`가 맡는다.

### 범위 결정 근거

이 plan은 alias 구현과 focused unit regression만 다룬다. Proto package/generated binding 수정은 predecessor 범위이며, cross-language scenario matrix 확장과 roadmap `fullname-tests` 완료는 후속 plan 범위다.

### 빌드 등급

`cloud-G07`: string identity가 parser, dispatch, pending correlation, public typed helpers를 관통하는 다중 언어 호환성 변경이다.

## 구현 체크리스트

- [ ] 구현 시작 전 `01_proto_fullname_foundation` complete.log로 predecessor 완료를 확인한다.
- [ ] 각 언어에 canonical full name과 legacy simple name을 같은 identity group으로 다루는 helper를 추가한다.
- [ ] parser map 등록 시 full/simple alias를 모두 등록하고, simple alias가 서로 다른 full name으로 충돌하면 initialize 단계에서 실패시킨다.
- [ ] listener/request handler 등록과 상호 배타 검사, inbound dispatch, pending response expected type 비교가 같은 alias 규칙을 사용하게 한다.
- [ ] 각 언어 focused unit test로 simple legacy receive와 alias collision을 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [ALIAS-1] Alias Registry Helpers

문제: current lookup은 exact key 중심이다.

```go
// go/communicator.go:497-503
parser := c.parserMap[typeName]
if parser == nil {
    return nil, fmt.Errorf("protobuf parser is not registered for type %s", typeName)
}
```

해결 방법: full name에서 마지막 segment를 simple alias로 계산하는 helper와 alias group lookup을 만든다. initialize에서 parserMap을 full/simple key로 normalize하되, 같은 simple alias가 다른 parser/full name으로 매핑되면 panic/error로 실패한다.

수정 파일 및 체크리스트:

- [ ] `go/communicator.go`
- [ ] `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`
- [ ] `python/proto_socket/communicator.py`
- [ ] `typescript/src/communicator.ts`
- [ ] `dart/lib/src/communicator.dart`

테스트 작성: 각 언어 communicator unit에 collision test를 추가한다.

중간 검증:

```bash
go test ./...
cd kotlin && ./gradlew test
cd python && python3 -m pytest -q
cd typescript && npm run check && npm test
dart test test/communicator_test.dart
```

### [ALIAS-2] Routing And Pending Matching

문제: dispatch와 pending response expected type 비교가 exact string이면 legacy simple-name response가 실패한다.

```typescript
// typescript/src/communicator.ts:580-589
if (typeName !== pending.expectedTypeName) {
  pending.reject(
    new Error(
      `response type mismatch for nonce ${responseNonce}: expected ${pending.expectedTypeName}, got ${typeName}`,
```

```python
# python/proto_socket/communicator.py:375-376
req_handler = self._req_handlers.get(item.type_name)
listeners = list(self._handlers.get(item.type_name, []))
```

해결 방법: incoming wire type을 canonical group으로 resolve한 뒤 parser, handler, listener, pending expected type 비교에 같은 canonical value를 사용한다. Error message는 original wire value와 expected canonical value를 모두 포함한다.

수정 파일 및 체크리스트:

- [ ] `go/communicator.go`
- [ ] `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`
- [ ] `python/proto_socket/communicator.py`
- [ ] `typescript/src/communicator.ts`
- [ ] `dart/lib/src/communicator.dart`

테스트 작성: request handler가 full name으로 등록되어도 incoming simple name을 처리하고, pending request expected full name이 incoming simple response를 수락하는 unit test를 추가한다.

중간 검증:

```bash
rg --sort path "typeName !=|expectedTypeName|expected_type_name|reqHandlers\\[|handlers\\[" go kotlin python typescript dart
```

### [ALIAS-3] HeartBeat Alias Consistency

문제: HeartBeat parser/listener는 각 언어에서 별도 자동 등록되며 alias에서 빠지기 쉽다.

```dart
// dart/lib/src/protobuf_client.dart:52-55
parserMap.addAll({
  (HeartBeat).toString(): HeartBeat.fromBuffer,
});
```

해결 방법: HeartBeat도 `proto_socket.HeartBeat`와 `HeartBeat` alias를 같은 registry helper로 등록한다. 자동 heartbeat listener 등록도 canonical helper를 통해 등록한다.

수정 파일 및 체크리스트:

- [ ] `dart/lib/src/protobuf_client.dart`
- [ ] `dart/lib/src/ws_protobuf_client_io.dart`
- [ ] `dart/lib/src/ws_protobuf_client_web.dart`
- [ ] `go/communicator.go`
- [ ] `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt`
- [ ] `python/proto_socket/communicator.py`
- [ ] `typescript/src/communicator.ts`

테스트 작성: focused HeartBeat alias unit test는 있으면 추가하고, 없으면 전체 heartbeat tests가 canonical helper를 통해 통과하는지 기록한다.

중간 검증:

```bash
dart test test/communicator_test.dart test/socket_test.dart
go test ./...
cd kotlin && ./gradlew test
cd python && python3 -m pytest -q
cd typescript && npm run check && npm test
```

## 의존 관계 및 구현 순서

`02+01_legacy_alias`는 sibling `01_proto_fullname_foundation`의 complete.log가 있어야 시작한다. active 후보는 `agent-task/m-protocol-evolution-compatibility/01_proto_fullname_foundation/complete.log`, archive 후보는 `agent-task/archive/*/*/m-protocol-evolution-compatibility/01_*/complete.log`다.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `dart/lib/src/communicator.dart`, `dart/lib/src/protobuf_client.dart`, `dart/lib/src/ws_protobuf_client_io.dart`, `dart/lib/src/ws_protobuf_client_web.dart` | ALIAS-1, ALIAS-2, ALIAS-3 |
| `go/communicator.go` | ALIAS-1, ALIAS-2, ALIAS-3 |
| `kotlin/src/main/kotlin/com/tokilabs/proto_socket/Communicator.kt` | ALIAS-1, ALIAS-2, ALIAS-3 |
| `python/proto_socket/communicator.py` | ALIAS-1, ALIAS-2, ALIAS-3 |
| `typescript/src/communicator.ts` | ALIAS-1, ALIAS-2, ALIAS-3 |
| `*/test/*communicator*` | ALIAS-1, ALIAS-2, ALIAS-3 |

## 최종 검증

```bash
dart test test/communicator_test.dart
go test ./...
cd kotlin && ./gradlew test
cd python && python3 -m pytest -q
cd typescript && npm run check && npm test
bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_matrix.sh --all
```

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