<!-- task=m-large-payload-followup-optimization/02_typescript_tcp_tail plan=0 tag=PERF -->

# TypeScript TCP 1024 Tail Timeout Plan

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

이 plan의 구현 완료 조건에는 대응 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션 작성이 포함된다. 구현 후 검증 명령을 실행하고 실제 출력, 계획 대비 변경, 주요 설계 결정을 채운 뒤 active 파일을 그대로 둔 채 리뷰 준비를 보고한다. 사용자만 결정할 수 있는 범위 변경, 외부 환경/secret/서비스 준비, 또는 구현을 안전하게 계속할 수 없는 충돌이 있으면 review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 기록하고 중단한다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 재실행으로 닫을 수 있는 검증 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

현 마일스톤의 `[typescript-tcp-1024-tail-path]`는 TypeScript TCP full parallel clients=1024에서 timeout 92건이 발생한 경로를 분리한다. 최근 full stress row는 `511908/512000` requests, throughput 22134.4 rps, p99 126.875ms였지만 timeout 92로 FAIL이다. 후보는 `Communicator.sendRequest`의 timeout 시작 시점, write queue backpressure, TCP transport write callback 지연이 섞이는 tail latency 경로다.

## 사용자 리뷰 요청 흐름

구현 중 사용자 결정이 필요한 경우 active `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` 형식으로 기록한다. 구현 에이전트는 직접 사용자 프롬프트를 만들지 않으며, code-review가 해당 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 판단한다.

## Roadmap Targets

- Milestone: `agent-roadmap/milestones/large-payload-followup-optimization.md`
- Task ids:
  - `typescript-tcp-1024-tail-path`: TypeScript TCP parallel clients=1024 timeout tail 재현, 측정, 수정 계획 수립
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-roadmap/current.md`
- `agent-roadmap/milestones/large-payload-followup-optimization.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-test/local/rules.md`
- `agent-test/local/proto-socket-performance-baseline.md`
- `agent-test/runs/20260613-141506-proto-socket-performance-full.md`
- `agent-test/runs/20260613-141506-proto-socket-stress-full.md`
- `typescript/src/communicator.ts`
- `typescript/src/tcp_client.ts`
- `typescript/src/tcp_server.ts`
- `typescript/src/base_client.ts`
- `typescript/bench/stress.ts`
- `typescript/test/communicator.test.ts`
- `typescript/test/tcp.test.ts`
- `typescript/package.json`

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md` 및 `agent-test/local/proto-socket-performance-baseline.md`를 읽었다.
- 대상 task에 명시된 검증 명령을 최종 검증에 포함한다: `run_stress.sh --full --lang typescript --transport tcp --profile parallel`, `run_performance.sh --quick`.
- layout 확인: `run_stress.sh`, `run_performance.sh`, `typescript/package.json`, `npm`, `bash` 존재 확인.

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

- `typescript/test/communicator.test.ts`에는 write queue cap과 timeout 테스트가 있지만, queue wait 중 timeout 시작 여부와 transport write 완료 후 response timeout 시작 여부를 분리하지 않는다.
- `typescript/test/tcp.test.ts`는 concurrent request 회귀가 있으나 1024 client tail은 unit test로 재현하기 어렵다. full stress가 필수 검증이다.

### 심볼 참조

- renamed/removed symbol: none.

### 분할 판단

- shared task group: `agent-task/m-large-payload-followup-optimization/`.
- sibling split은 `01_typescript_ws_1mb`, `02_typescript_tcp_tail`, `03_kotlin_tcp_parallel`, `04_ws_fixed_latency`, `05_dart_large_packet_guard`이며 모두 독립이다.
- 본 작업은 TypeScript TCP send/write/timeout semantics만 다루며 Kotlin TCP required skip과 독립이다.

### 범위 결정 근거

- WebSocket frame masking, Kotlin read dispatcher, Dart payload guard는 제외한다.
- stress harness의 parallel matrix는 재현에 사용하되, clients/perClient 값을 완화해 PASS로 만드는 변경은 금지한다.

### 빌드 등급

- `cloud-G07`: terminal benchmark-style full stress 재현과 concurrency/timeout semantics가 핵심이며 실패 모드가 tail에 숨어 있어 cloud lane으로 둔다.

## 구현 체크리스트

- [ ] [PERF-1] `Communicator.sendRequest`의 request timeout과 write queue/write completion 구간을 분리해 queue wait가 response timeout으로 오인되지 않게 한다.
- [ ] [PERF-2] TCP parallel 1024 timeout tail을 재현/계측하고 full stress hard gate 0을 확인한다.
- [ ] 대상 task 검증 명령인 TypeScript TCP full parallel stress, quick performance를 실행하고 결과 기록 파일 경로를 review stub에 남긴다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [PERF-1] sendRequest timeout phase 분리

문제: `typescript/src/communicator.ts:370-410`에서 pending request timer가 `queuePacket` 완료 전 시작된다. `typescript/src/communicator.ts:616-650`의 write loop는 packet을 하나씩 transport에 쓰므로 1024 client tail에서 write queue wait가 response timeout으로 집계될 수 있다.

해결 방법:

```ts
// before: typescript/src/communicator.ts:382
const timer = setTimeout(() => {
  this.pendingRequests.delete(nonce);
  reject(new Error("request timeout"));
}, timeoutMs);
...
await this.queuePacket(packet);
```

```ts
// after: shape
await this.queuePacket(packet);
const timer = setTimeout(() => {
  this.pendingRequests.delete(nonce);
  reject(new Error("request timeout"));
}, timeoutMs);
```

- queue/write 실패 시 pending cleanup을 반드시 유지한다.
- queue wait 자체가 무한 대기하지 않도록 기존 write queue backpressure test를 깨지 않는 별도 write enqueue timeout 또는 rejection 경로를 검토한다.
- response timeout의 의미가 바뀌므로 test에서 "write가 막힌 동안 response timer가 먼저 터지지 않는다"를 고정한다.

수정 파일 및 체크리스트:

- [ ] `typescript/src/communicator.ts`: pending 등록, queuePacket, timer 시작, cleanup 순서를 재구성한다.
- [ ] `typescript/test/communicator.test.ts`: delayed/blocked transport로 queue/write 구간과 response timeout 구간을 분리 검증한다.

테스트 작성: regression test 필수. `BlockingTransport` 또는 새 delayed transport fixture로 write promise가 풀리기 전 timeout이 발생하지 않고, write 후 response timeout은 정상 발생하는지 검증한다.

중간 검증:

```bash
cd typescript && npm test -- test/communicator.test.ts
```

예상 결과: exit 0, timeout/write queue 관련 기존 테스트와 신규 regression PASS.

### [PERF-2] 1024 client tail 재현과 stress hard gate

문제: `typescript/bench/stress.ts:554-603` full parallel은 clients `[16,128,512,1024]`, perClient 500, timeout 15s로 실제 tail failure를 드러낸다. 단위 테스트만으로 92건 timeout을 대체할 수 없다.

해결 방법:

```ts
// before: typescript/bench/stress.ts:554
const clientCounts = mode === "quick" ? [4] : [16, 128, 512, 1024];
```

```ts
// after: keep matrix; add focused evidence only if needed
const clientCounts = mode === "quick" ? [4] : [16, 128, 512, 1024];
```

- stress matrix는 축소하지 않는다.
- 필요하면 TypeScript stress stderr에 clients=1024 row의 timeout count와 result record path가 잘 보이도록만 보강한다.
- PASS 조건은 clients=1024 row timeout 0, nonce/type/FIFO/pending leak 0이다.

수정 파일 및 체크리스트:

- [ ] `typescript/bench/stress.ts`: matrix 축소 없이 필요한 계측만 추가한다.
- [ ] `typescript/test/tcp.test.ts`: TCP request concurrency 회귀가 timeout semantics 변경 후에도 PASS하는지 확인한다.

테스트 작성: high-client stress는 harness 검증으로 처리한다. 추가 unit test는 PERF-1에서 작성한다.

중간 검증:

```bash
bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --lang typescript --transport tcp --profile parallel
```

예상 결과: exit 0, TypeScript TCP `parallel / clients=1024` row PASS, Timeout 0.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `typescript/src/communicator.ts` | PERF-1 |
| `typescript/test/communicator.test.ts` | PERF-1 |
| `typescript/test/tcp.test.ts` | PERF-2 |
| `typescript/bench/stress.ts` | PERF-2 |

## 최종 검증

```bash
cd typescript && npm run check
cd typescript && npm test -- test/communicator.test.ts test/tcp.test.ts
bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_stress.sh --full --lang typescript --transport tcp --profile parallel
bash agent-ops/skills/project/run-proto-socket-test-matrix/scripts/run_performance.sh --quick
```

예상 결과: TypeScript unit/check 명령 exit 0. full parallel stress는 TypeScript TCP clients=1024 Timeout 0, 전체 결과 PASS. quick performance는 전체 component FAIL 없이 완료되어야 하며, 타 언어 toolchain 문제로 BLOCKED/INCOMPLETE가 발생하면 해당 사유와 TypeScript TCP target row PASS 증거를 review stub에 분리 기록한다.

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