<!-- task=m-codex-app-server-streaming-migration/01_appserver_rpc_client plan=2 tag=REVIEW_REVIEW_API -->
# Codex App Server RPC Client Follow-up Plan 2

## 이 파일을 읽는 구현 에이전트에게
이 PLAN을 끝까지 읽은 뒤 구현한다. 범위 밖 리팩터링, archive 읽기, 사용자 변경 되돌리기는 금지한다. 코드 변경 전 관련 domain rule과 local test rule을 확인하고, 구현 완료 전 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션을 실제 변경 내용과 검증 출력으로 채운다.

구현 중 사용자 소유 인증, 외부 계정 상태, 또는 범위 변경 없이는 안전하게 진행할 수 없을 때만 `CODE_REVIEW-cloud-G07.md`의 사용자 리뷰 요청 섹션을 실제 내용으로 교체하고 중단한다. 직접 사용자에게 질문하거나 선택지를 제시하지 않는다. 단순 검증 로그 부족은 구현 에이전트가 재실행으로 해소한다.

## 배경
이 follow-up은 `code_review_cloud_G07_1.log`의 FAIL 판정에서 나온 Required 이슈만 처리한다. `thread/start` thread id 누락 검증은 통과했으므로 다시 넓히지 않는다. 남은 범위는 `send()`의 첫 번째 `writeErr`/`p.done` 경합과, 실제 `send()` 경로를 검증하지 않는 보조 테스트 수정이다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/codex-app-server-streaming-migration.md`
- Task ids:
  - `mode-router`: CLI adapter에 `codex-app-server` mode를 추가하고 executor/session reporter 라우팅을 분리한다.
  - `rpc-lifecycle`: `codex app-server --stdio` 프로세스를 시작한 뒤 `initialize`, `initialized`, `thread/start`, `turn/start` 흐름을 안정적으로 처리한다.
- Completion mode: check-on-pass

## 이전 리뷰 요약
- Archived plan: `agent-task/m-codex-app-server-streaming-migration/01_appserver_rpc_client/plan_cloud_G07_1.log`
- Archived review: `agent-task/m-codex-app-server-streaming-migration/01_appserver_rpc_client/code_review_cloud_G07_1.log`
- Verdict: FAIL
- Required:
  - `apps/node/internal/adapters/cli/codex_app_server.go:274`에서 첫 번째 `select`가 `p.done`을 선택하면 response channel 확인 없이 `process exited`를 반환한다.
  - `apps/node/internal/adapters/cli/codex_app_server_internal_test.go:406`의 새 테스트가 `send()`를 호출하지 않아 실제 경합을 검증하지 못한다.

## 구현 체크리스트
- [ ] `send()`의 write 단계에서도 process exit보다 이미 도착한 response를 우선 반환하도록 수정한다.
- [ ] `TestCodexAppServerSend_ResponsePriorityOverDone`를 실제 `send()` 경로를 검증하는 테스트로 바꾸거나 제거하고, 기존 반복 테스트가 경합 회귀를 잡도록 정리한다.
- [ ] `go test ./apps/node/internal/adapters/cli -run '^TestCodexAppServerSend_RequestIDMonotone$' -count=200 -timeout=60s`, `go test ./apps/node/internal/adapters/cli -count=1 -timeout=60s`, `go test ./apps/node/... -count=1 -timeout=120s` 결과를 `CODE_REVIEW-cloud-G07.md`에 실제 stdout/stderr로 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REVIEW_API-1] `send()` write 단계의 response/process-exit 경합 수정
문제: 현재 `send()`는 stdin write 완료를 기다리는 첫 번째 `select`에서 `p.done`이 선택되면 바로 `process exited`를 반환한다. 서버가 요청을 읽고 response를 쓴 직후 stdout을 닫으면 `writeErr`, response dispatch, `p.done`이 가까운 시점에 ready가 되어 여전히 valid response가 묻힐 수 있다.

해결 방법: 첫 번째 `p.done` 분기에서도 response channel을 비차단으로 확인하고, 이미 dispatch된 response가 있으면 기존 RPC error 처리 규칙까지 동일하게 적용해 반환한다. 더 안전한 구조가 필요하면 response 처리 helper를 분리해 첫 번째/두 번째 wait 모두 같은 우선순위 규칙을 쓰게 한다. `ctx.Done()`은 기존처럼 우선 취소 semantics를 유지한다.

수정 파일 및 체크리스트:
- [ ] `apps/node/internal/adapters/cli/codex_app_server.go`
- [ ] `apps/node/internal/adapters/cli/codex_app_server_internal_test.go`

테스트 작성:
- [ ] `TestCodexAppServerSend_RequestIDMonotone`가 `-count=200`에서도 안정적으로 통과하도록 실제 `send()` 경로를 수정한다.

중간 검증:
```bash
go test ./apps/node/internal/adapters/cli -run '^TestCodexAppServerSend_RequestIDMonotone$' -count=200 -timeout=60s
```

### [REVIEW_REVIEW_API-2] 실제 경합을 검증하지 않는 보조 테스트 교체
문제: `TestCodexAppServerSend_ResponsePriorityOverDone`는 `send()`를 호출하지 않고 preloaded channel을 직접 읽는다. 이 테스트는 `send()`의 select 구조가 바뀌어도 실패하지 않으므로 회귀 방지 가치가 없다.

해결 방법: 해당 테스트를 실제 `send()` 호출 기반으로 바꾸거나, 기존 `TestCodexAppServerSend_RequestIDMonotone` 반복 검증이 충분히 실제 경합을 재현한다면 제거한다. 남기는 테스트는 stdin write, response dispatch, done close가 모두 실제 `send()` 흐름을 통과해야 한다.

수정 파일 및 체크리스트:
- [ ] `apps/node/internal/adapters/cli/codex_app_server_internal_test.go`

테스트 작성:
- [ ] `send()`를 우회하는 select-only 테스트를 남기지 않는다.
- [ ] 새/수정 테스트가 실패 시 `send()` 실제 반환값으로 실패하도록 만든다.

중간 검증:
```bash
go test ./apps/node/internal/adapters/cli -run 'TestCodexAppServerSend' -count=50 -timeout=60s
```

## 범위 결정 근거
`thread/start` thread id 누락 error와 테스트는 이번 리뷰에서 통과했다. 이번 follow-up은 남은 RPC send 경합과 테스트 신뢰성만 닫는다.

## 리뷰어를 위한 체크포인트
- `send()`의 두 wait 지점 모두 response 우선 규칙을 적용하는지 확인한다.
- `ctx.Done()` 취소, RPC error response, pending cleanup이 유지되는지 확인한다.
- `TestCodexAppServerSend_ResponsePriorityOverDone`가 실제 `send()`를 호출하거나 제거됐는지 확인한다.
- 구현자가 기록한 focused 반복 검증이 실제로 통과하는지 재실행한다.

## 최종 검증
```bash
go test ./apps/node/internal/adapters/cli -run '^TestCodexAppServerSend_RequestIDMonotone$' -count=200 -timeout=60s
go test ./apps/node/internal/adapters/cli -run 'TestCodexAppServerSend' -count=50 -timeout=60s
go test ./apps/node/internal/adapters/cli -count=1 -timeout=60s
go test ./apps/node/... -count=1 -timeout=120s
```

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