<!-- task=02_dart_typescript_process_cleanup plan=0 tag=CROSSTEST_PROCESS -->

# Plan - CROSSTEST_PROCESS

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

**구현 마지막 단계에서 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 반드시 채워야 한다. 이 파일이 비어 있으면 작업은 완료가 아니다.**
구현 체크리스트를 기준으로 작업하고, 계획과 리뷰 stub의 체크리스트를 모두 완료하며, 중간/최종 검증을 실행한 실제 출력을 리뷰 파일에 기록한다. 리뷰 파일의 `이 파일을 읽는 리뷰 에이전트에게`에 있는 archive 지시와 `코드리뷰 전용 체크리스트`는 리뷰 에이전트 전용이므로 실행하거나 수정하지 않는다.

## 배경

Dart server의 TypeScript client crosstest는 `npx tsx` wrapper를 실행하고 timeout 시 직접 process만 kill한다. `npx`가 child process를 남기거나 stream completion이 지연되면 orchestrator가 멈출 수 있다. Kotlin의 최근 보강 방향과 맞춰 직접 `node_modules/.bin/tsx`를 실행하고 stream wait도 bounded 처리한다.

## 분석 결과

### 읽은 파일

- `dart/crosstest/dart_typescript.dart`
- `README.md`

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

- timeout 경로의 child cleanup과 stream completion: 별도 회귀 테스트 없음.
- 정상 경로의 TypeScript client PASS line parsing: `dart run crosstest/dart_typescript.dart`가 TCP/WS/TLS/WSS 정상 경로를 확인한다.

### 심볼 참조

- renamed/removed symbol: none.
- `_runTypescriptClient` call site: `dart/crosstest/dart_typescript.dart:119`, `:139`, `:161`, `:181`, `:225`, `:247`, `:269`, `:290`.

### 분할 판단

split decision policy를 먼저 평가했다. 이 task는 Dart 도메인의 한 runner 파일만 다룬다. Go/Python의 subprocess API는 다르고 Kotlin runner 정리도 별도 검증을 가지므로 sibling task로 분리했다.

Sibling task:

- `01_kotlin_subprocess_cleanup`: Kotlin server runner 정리.
- `02_dart_typescript_process_cleanup`: 이 task.
- `03_go_typescript_process_cleanup`: Go server runner 정리.
- `04_python_typescript_process_cleanup`: Python server runner 정리.

### 범위 결정 근거

`dart/crosstest/dart_go.dart`, `dart/crosstest/dart_python.dart`, `dart/crosstest/dart_kotlin.dart`는 TypeScript wrapper 문제가 아니므로 제외한다. Dart core implementation과 TypeScript client helper는 변경하지 않는다.

### 빌드 등급

build=`cloud-G07`, review=`cloud-G07`. Dart process spawning, stdout/stderr stream handling, timeout contract를 다루는 terminal-agent 작업이다.

## 구현 체크리스트

- [ ] [CROSSTEST_PROCESS-1] Dart server TypeScript client runner가 로컬 `tsx`를 직접 실행하고 timeout/stream wait를 bounded 처리한다.
- [ ] 중간 검증과 최종 검증 명령을 실행하고 실제 출력을 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [CROSSTEST_PROCESS-1] Dart TypeScript subprocess cleanup

#### 문제

`dart/crosstest/dart_typescript.dart:298`은 `Process.start('npx', ['tsx', ...])`를 사용한다. timeout 시 `dart/crosstest/dart_typescript.dart:328`에서 exitCode timeout 후 process만 kill하고, `dart/crosstest/dart_typescript.dart:332`에서 stream future를 무제한 대기한다.

#### 해결 방법

`_typescriptDir` 아래 `node_modules/.bin/tsx` 경로를 계산해 직접 실행한다. timeout 시 process kill 후 stdout/stderr stream future 대기는 별도 timeout으로 감싸고, stream이 닫히지 않으면 명확한 `StateError`를 발생시킨다.

Before (`dart/crosstest/dart_typescript.dart:298`):

```dart
final process = await Process.start(
  'npx',
  [
    'tsx',
    'crosstest/dart_typescript_client.ts',
```

After:

```dart
final tsxBin = '$_typescriptDir/node_modules/.bin/tsx';
final process = await Process.start(
  tsxBin,
  [
    'crosstest/dart_typescript_client.ts',
```

Before (`dart/crosstest/dart_typescript.dart:328`):

```dart
final code = await process.exitCode.timeout(_processTimeout, onTimeout: () {
  process.kill(ProcessSignal.sigkill);
  return -1;
});
await Future.wait([stdoutDone, stderrDone]);
```

After:

```dart
final code = await process.exitCode.timeout(_processTimeout, onTimeout: () {
  process.kill(ProcessSignal.sigkill);
  return -1;
});
await Future.wait([stdoutDone, stderrDone])
    .timeout(_streamTimeout, onTimeout: () {
  throw StateError('typescript-client $mode/$phase streams did not finish');
});
```

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

- [ ] `dart/crosstest/dart_typescript.dart`: `_streamTimeout` 추가.
- [ ] `dart/crosstest/dart_typescript.dart`: `npx tsx` 대신 local `tsx` 직접 실행.
- [ ] `dart/crosstest/dart_typescript.dart`: stdout/stderr stream future에 bounded timeout 적용.

#### 테스트 작성

별도 테스트 파일은 작성하지 않는다. 변경 대상은 crosstest executable이고, 정상 경로는 기존 full crosstest가 검증한다. timeout fixture 추가는 별도 task로 분리할 수 있다.

#### 중간 검증

```bash
cd dart
dart run crosstest/dart_typescript.dart
```

예상 결과: `PASS all dart-server/typescript-client crosstests passed`.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `dart/crosstest/dart_typescript.dart` | CROSSTEST_PROCESS-1 |

## 최종 검증

```bash
cd dart
dart run crosstest/dart_typescript.dart
```

예상 결과: PASS.

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