<!-- task=crosstest_typescript plan=0 tag=CROSSTEST -->

# Code Review Reference - CROSSTEST

## 개요

date=2026-04-24
task=crosstest_typescript, plan=0, tag=CROSSTEST

## 이 파일을 읽는 리뷰 에이전트에게

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.

1. `CODE_REVIEW.md` → `code_review_0.log` (N = 기존 code_review_*.log 수)
2. `PLAN.md` → `plan_0.log` (M = 기존 plan_*.log 수)
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 `PLAN.md` + `CODE_REVIEW.md` 스텁 작성.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [CROSSTEST-1] Dart 서버 → TypeScript 클라이언트 | [x] |
| [CROSSTEST-2] Kotlin 서버 → TypeScript 클라이언트 | [x] |
| [CROSSTEST-3] Python 서버 → TypeScript 클라이언트 | [x] |
| [CROSSTEST-4] TypeScript 서버 → Dart 클라이언트 | [x] |
| [CROSSTEST-5] TypeScript 서버 → Go 클라이언트 | [x] |
| [CROSSTEST-6] TypeScript 서버 → Kotlin 클라이언트 | [x] |
| [CROSSTEST-7] TypeScript 서버 → Python 클라이언트 | [x] |

## 계획 대비 변경 사항

- Python 실행 명령은 계획의 `python` 대신 기존 프로젝트 패턴과 실제 실행 환경에 맞춰 `python3`를 사용했다.
- TypeScript 서버 row 검증 명령은 계획의 `npx tsx ...` 대신 `node --import tsx ...`로 실행했다.
  이유: `tsx` CLI가 sandbox 환경에서 IPC pipe listen(`EPERM`)에 실패했지만, 동일 스크립트를 `node --import tsx`로 실행하면 정상 동작했다.
- `kotlin/crosstest/kotlin_typescript.kt`의 WebSocket phase는 동일 포트(`29796`) 재기동이 불안정해서, 서버를 한 번만 띄우고 `send-push`/`requests` 두 phase를 순차 실행하도록 조정했다.
  이유: Kotlin `WsServer.start()`가 비동기라 같은 포트 재시작 직후 TypeScript 클라이언트 연결이 반복적으로 `ECONNREFUSED`를 반환했다.

## 주요 설계 결정

- Phase 1 TypeScript 클라이언트 3개는 `go_typescript_client.ts` 구조를 그대로 유지하고, push 기대 문자열과 로그만 서버 언어별로 바꿨다.
- TypeScript 서버 row는 pairwise 오케스트레이터 4개를 각각 만들되, 모든 파일에서 같은 subprocess PASS/FAIL 파서와 TCP/WS phase 분리 패턴을 유지했다.
- Kotlin 서버 → TypeScript 클라이언트 조합은 TypeScript 클라이언트에 짧은 연결 안정화 지연을 추가하고, Kotlin WebSocket 서버는 단일 인스턴스 재사용으로 고정해 flaky 재기동을 제거했다.
- 검증은 Dart/TypeScript/Python 정적 검사, Go 테스트, Kotlin crosstest compile까지 먼저 확인한 뒤 언어 matrix crosstest를 순서대로 실행했다.

## 리뷰어를 위한 체크포인트

- 각 오케스트레이터의 포트가 PLAN.md 포트 배정표와 일치하는지 확인.
- 각 TypeScript 클라이언트 헬퍼의 기대 push 메시지가 서버 언어와 맞는지 확인.  
  (`"push from dart server"`, `"push from kotlin server"`, `"push from python server"`, `"push from typescript server"`)
- TypeScript 서버 오케스트레이터에서 `"fire from <lang> client"` 검증 메시지가 서버 언어와 맞는지 확인.
- `go/crosstest/typescript_go_client/main.go`의 package가 `main`이고 `//go:build ignore`가 없는지 확인.
- `kotlin/crosstest/typescript_kotlin_client.kt`의 `@file:JvmName("TypescriptKotlinClientKt")`이 정확한지 확인.
- 각 TypeScript 오케스트레이터에서 서버 stop이 finally 블록에서 수행되는지 확인.
- 검증 결과: 7개 중간 검증 + Go→TypeScript 회귀 검증 모두 PASS인지 확인.

## 검증 결과

### CROSSTEST-1 중간 검증
```
$ cd dart && dart run crosstest/dart_typescript.dart
INFO typeName dart=TestData
INFO typeName ts=TestData
PASS scenario=1 detail=fire-and-forget sent
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=2 detail=received push from dart server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
INFO typeName ts=TestData
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from dart server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all dart-server/typescript-client crosstests passed
```

### CROSSTEST-2 중간 검증
```
$ cd kotlin && ./gradlew run -PmainClass=com.tokilabs.toki_socket.crosstest.KotlinTypescriptKt
INFO typeName kotlin=TestData
INFO typeName ts=TestData
PASS scenario=1 detail=fire-and-forget sent
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=2 detail=received push from kotlin server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
INFO typeName ts=TestData
PASS scenario=1 detail=fire-and-forget sent
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=2 detail=received push from kotlin server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all kotlin-server/typescript-client crosstests passed
BUILD SUCCESSFUL
```

### CROSSTEST-3 중간 검증
```
$ cd python && python3 -m crosstest.python_typescript
INFO typeName python=TestData
SERVER_RECEIVED index=101 message=fire from typescript client
INFO typeName ts=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from python server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
SERVER_RECEIVED index=101 message=fire from typescript client
INFO typeName ts=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from python server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all python-server/typescript-client crosstests passed
```

### CROSSTEST-4 중간 검증
```
$ cd typescript && node --import tsx crosstest/typescript_dart.ts
INFO typeName ts=TestData
INFO typeName dart=TestData
SERVER_RECEIVED index=101 message=fire from dart client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName dart=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
INFO typeName dart=TestData
SERVER_RECEIVED index=101 message=fire from dart client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName dart=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all typescript-server/dart-client crosstests passed
```

### CROSSTEST-5 중간 검증
```
$ cd typescript && env PATH=/config/go-sdk/go/bin:/config/go/bin:$PATH GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod node --import tsx crosstest/typescript_go.ts
INFO typeName ts=TestData
INFO typeName go=TestData
SERVER_RECEIVED index=101 message=fire from go client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName go=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
INFO typeName go=TestData
SERVER_RECEIVED index=101 message=fire from go client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName go=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all typescript-server/go-client crosstests passed
```

### CROSSTEST-6 중간 검증
```
$ cd typescript && env JAVA_HOME=/config/opt/jdk/jdk-17.0.10+7 GRADLE_USER_HOME=/tmp/gradle node --import tsx crosstest/typescript_kotlin.ts
INFO typeName ts=TestData
> Task :run
INFO typeName kotlin=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
BUILD SUCCESSFUL
> Task :run
INFO typeName kotlin=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
BUILD SUCCESSFUL
> Task :run
INFO typeName kotlin=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
BUILD SUCCESSFUL
> Task :run
INFO typeName kotlin=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
BUILD SUCCESSFUL
PASS all typescript-server/kotlin-client crosstests passed
```

### CROSSTEST-7 중간 검증
```
$ cd typescript && node --import tsx crosstest/typescript_python.ts
INFO typeName ts=TestData
SERVER_RECEIVED index=101 message=fire from python client
INFO typeName python=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName python=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
SERVER_RECEIVED index=101 message=fire from python client
INFO typeName python=TestData
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from typescript server
INFO typeName python=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all typescript-server/python-client crosstests passed
```

### 최종 검증
```
$ cd go && env PATH=/config/go-sdk/go/bin:/config/go/bin:$PATH GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go run ./crosstest/go_typescript.go
INFO typeName go=TestData
INFO typeName ts=TestData
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from go server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
INFO typeName ts=TestData
SERVER_RECEIVED index=101 message=fire from typescript client
PASS scenario=1 detail=fire-and-forget sent
PASS scenario=2 detail=received push from go server
INFO typeName ts=TestData
PASS scenario=3 detail=single request response matched
PASS scenario=4 detail=concurrent request responses matched
PASS all go-server/typescript-client crosstests passed
```

### 보조 검증
```
$ dart analyze dart/crosstest/dart_typescript.dart dart/crosstest/typescript_dart_client.dart
No issues found!

$ cd typescript && npx tsc --noEmit
(exit 0)

$ python3 -m py_compile python/crosstest/python_typescript.py python/crosstest/typescript_python_client.py
(exit 0)

$ cd go && PATH=/config/go-sdk/go/bin:/config/go/bin:$PATH GOCACHE=/tmp/go-build GOMODCACHE=/tmp/go-mod go test ./...
?   	toki-labs.com/toki_socket/go	[no test files]
?   	toki-labs.com/toki_socket/go/crosstest/dart_go_client	[no test files]
?   	toki-labs.com/toki_socket/go/crosstest/kotlin_go_client	[no test files]
?   	toki-labs.com/toki_socket/go/crosstest/python_go_client	[no test files]
?   	toki-labs.com/toki_socket/go/crosstest/typescript_go_client	[no test files]
?   	toki-labs.com/toki_socket/go/examples/tcp_echo	[no test files]
?   	toki-labs.com/toki_socket/go/examples/ws_echo	[no test files]
?   	toki-labs.com/toki_socket/go/packets	[no test files]
ok  	toki-labs.com/toki_socket/go/test	4.051s

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

$ git diff --check
(no output)
```
