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

# TypeScript WS 1MB Payload Hot Path Plan

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

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

## 배경

현 마일스톤의 `[typescript-ws-1mb-path]`는 TypeScript WebSocket 1MB payload 경로가 다른 언어 대비 낮은 처리량을 보이는 병목을 분리해 처리해야 한다. 최근 full 결과에서 안정성은 PASS였지만 1MB WS throughput은 TypeScript 50.5 rps, Go 317.7 rps, Python 169.7 rps로 차이가 크다. 병목 후보는 `node_ws_client.ts`의 WebSocket frame masking/copy와 `PacketBase` serialize 후 추가 Buffer 변환 경로에 집중된다.

## 사용자 리뷰 요청 흐름

구현 중 사용자 결정이 필요한 경우 active `CODE_REVIEW-local-G06.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-ws-1mb-path`: TypeScript WS 1MB payload 병목 후보 경로 분리, 개선/측정 계획 수립
- 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/node_ws_client.ts`
- `typescript/src/node_ws_server.ts`
- `typescript/src/communicator.ts`
- `typescript/bench/stress.ts`
- `typescript/test/ws.test.ts`
- `typescript/test/communicator.test.ts`
- `typescript/package.json`
- `typescript/tsconfig.json`

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`를 읽었고 성능/스트레스 작업은 `proto-socket-performance-baseline` profile로 라우팅된다.
- 읽은 profile: `agent-test/local/proto-socket-performance-baseline.md`.
- 적용 명령은 repository script와 profile의 성능 baseline 기준을 따른다. 안정성 hard gate는 timeout/nonce/type/FIFO/pending leak 0이다.
- plan 작성 전 layout 확인: `run_stress.sh`, `run_performance.sh`, `typescript/package.json`, `npm`, `bash` 존재를 확인했다.

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

- 기존 `typescript/test/ws.test.ts`는 1MB WS request/response와 fragmented binary frame을 다루지만, frame masking 결과 동등성이나 1MB masking hot path copy 수를 직접 고정하지 않는다.
- 기존 stress payload row는 1MB 성능을 기록하지만 절대 throughput을 hard fail로 삼지 않는다. 이 plan은 안정성 유지와 전후 성능 row 기록을 완료 조건으로 둔다.

### 심볼 참조

- renamed/removed symbol: none.

### 분할 판단

- shared task group: `agent-task/m-large-payload-followup-optimization/`.
- sibling split:
  - `01_typescript_ws_1mb`: TypeScript WS 1MB hot path. 독립, 선행 없음.
  - `02_typescript_tcp_tail`: TypeScript TCP 1024 tail timeout. 독립.
  - `03_kotlin_tcp_parallel`: Kotlin TCP parallel required skip 해소. 독립.
  - `04_ws_fixed_latency`: WS fixed latency 공통/transport 진단. 독립.
  - `05_dart_large_packet_guard`: Dart 1MB guard. 독립.
- 본 작업은 TypeScript WS transport 내부 최적화로 한정되며 다른 sibling 완료를 기다리지 않는다.

### 범위 결정 근거

- TypeScript TCP timeout semantics, Kotlin/Dart 구현, cross-language protocol schema는 제외한다.
- `ws` npm package fallback 경로는 public fallback 유지 여부만 회귀로 확인하고, custom `NodeWebSocket` hot path를 우선 대상으로 한다.

### 빌드 등급

- `local-G06`: 단일 언어/transport의 bounded hot path이고 기존 unit/stress 검증으로 리뷰 가능하지만, binary frame 처리와 성능 회귀 위험이 있어 중간 등급으로 둔다.

## 구현 체크리스트

- [ ] [PERF-1] `NodeWebSocket` 1MB binary frame encode/decode hot path의 불필요한 copy와 byte-wise masking 비용을 줄인다.
- [ ] [PERF-2] WS frame masking/1MB payload 회귀 테스트를 추가 또는 보강하고 TypeScript check/test를 통과시킨다.
- [ ] TypeScript WS payload full stress를 실행해 1MB row의 안정성 hard gate가 0이고 전후 throughput/p99가 기록됐는지 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [PERF-1] WS frame hot path 최적화

문제: `typescript/src/node_ws_client.ts:440-450`에서 `PacketBase`를 serialize한 뒤 `NodeWebSocket.send`로 넘기고, `typescript/src/node_ws_client.ts:690-750`에서 client outbound masking을 새 Buffer와 byte loop로 처리한다. 1MB payload에서는 이 copy/loop가 row throughput을 직접 제한한다.

해결 방법:

```ts
// before: typescript/src/node_ws_client.ts:745
function maskPayload(payload: Uint8Array, maskingKey: Buffer): Buffer {
  const output = Buffer.allocUnsafe(payload.byteLength);
  for (let i = 0; i < payload.byteLength; i++) {
    output[i] = payload[i]! ^ maskingKey[i & 3]!;
  }
  return output;
}
```

```ts
// after: shape, keep RFC6455 masking semantics
function maskPayload(payload: Uint8Array, maskingKey: Buffer): Buffer {
  const output = Buffer.from(payload);
  xorMaskInPlace(output, maskingKey);
  return output;
}
```

- shared helper는 `unmaskInPlace`와 outbound masking이 같은 검증 경로를 타도록 만든다.
- tail byte 처리를 포함해 payload length 0, 1, 2, 3, 4, 1MB를 모두 보존한다.
- callback/error semantics와 close frame behavior는 바꾸지 않는다.

수정 파일 및 체크리스트:

- [ ] `typescript/src/node_ws_client.ts`: mask/unmask helper를 통합하고 1MB payload에서 추가 copy를 줄인다.
- [ ] `typescript/src/node_ws_client.ts`: `writeFrame` header/payload write 순서와 callback 호출 의미를 유지한다.

테스트 작성: `typescript/test/ws.test.ts`에 masked frame roundtrip 또는 fragmented 1MB frame assertion을 보강한다. 기존 1MB request/response 테스트만으로 masking helper의 tail 처리 결함을 잡기 어렵다.

중간 검증:

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

예상 결과: exit 0, WS 1MB/fragmentation/masking 관련 테스트 PASS.

### [PERF-2] 1MB payload 회귀 증거 고정

문제: `typescript/bench/stress.ts:703-777`은 full payload 1MB row를 기록하지만 구현 전후 차이를 구현 리뷰 파일에 남기지 않으면 병목 개선 여부를 판정하기 어렵다.

해결 방법:

```ts
// before: typescript/bench/stress.ts:703
const sizes = mode === "quick" ? payloadSizesQuick : payloadSizesFull;
```

```ts
// after: same matrix, but review evidence must include the full ws payload row
const sizes = mode === "quick" ? payloadSizesQuick : payloadSizesFull;
```

- stress matrix 자체가 충분하면 소스 변경은 하지 않는다.
- 구현 리뷰에 최신 baseline row와 변경 후 row를 모두 붙인다.
- 성능 수치가 환경 의존이므로 절대 threshold 추가는 이 plan 범위에서 제외한다.

수정 파일 및 체크리스트:

- [ ] `typescript/test/ws.test.ts`: 1MB payload가 custom NodeWebSocket 경로를 사용하도록 test fixture를 유지한다.
- [ ] `typescript/bench/stress.ts`: 필요한 경우 1MB WS payload row를 식별하기 쉬운 stderr log만 추가한다.

테스트 작성: stress row 자체가 통합 검증이다. unit test는 PERF-1에서 작성한다.

중간 검증:

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

예상 결과: exit 0, `payload=1MB / TypeScript / ws` row PASS, timeout/nonce/type/FIFO/pending leak 0.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `typescript/src/node_ws_client.ts` | PERF-1 |
| `typescript/test/ws.test.ts` | PERF-1, PERF-2 |
| `typescript/bench/stress.ts` | PERF-2 |

## 최종 검증

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

예상 결과: 모든 명령 exit 0. TypeScript WS payload full row는 PASS이고 1MB row의 stability counter가 모두 0이다. performance quick은 component FAIL 없이 PASS 또는 baseline 미지정 regression SKIPPED로 기록된다.

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