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

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

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

## 배경
이 follow-up은 `code_review_cloud_G07_0.log`의 FAIL 판정에서 나온 Required 이슈만 처리한다. app-server mode 라우팅 자체는 유지하되, newline RPC response와 process exit의 경합, 그리고 `thread/start` 결과 검증 누락을 수정한다.

## 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_0.log`
- Archived review: `agent-task/m-codex-app-server-streaming-migration/01_appserver_rpc_client/code_review_cloud_G07_0.log`
- Verdict: FAIL
- Required:
  - `apps/node/internal/adapters/cli/codex_app_server.go:285`에서 response와 `p.done`이 동시에 ready일 때 valid response 대신 `process exited`가 반환될 수 있다.
  - `apps/node/internal/adapters/cli/codex_app_server.go:341`에서 `thread/start` response의 thread id가 비어도 초기화 성공으로 처리한다.

## 구현 체크리스트
- [ ] `send`가 response와 `p.done` 경합에서 이미 도착한 response를 우선 반환하도록 수정한다.
- [ ] `codexAppServerInit`이 `thread/start` 응답의 thread id 누락을 error로 반환하고 missing-id 회귀 테스트를 추가한다.
- [ ] `go test ./apps/node/internal/adapters/cli -run '^TestCodexAppServerSend_RequestIDMonotone$' -count=20 -timeout=30s`, `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_API-1] `send` response/process-exit 경합 수정
문제: `codexAppServerProc.send`가 response channel과 `p.done`을 같은 `select`에서 기다린다. 서버가 response를 쓴 직후 stdout을 닫으면 둘 다 ready가 되고, Go select가 `p.done`을 고르면 이미 받은 response가 무시된다. 이 때문에 `TestCodexAppServerSend_RequestIDMonotone`가 반복 실행에서 `send 2: codex app-server process exited`로 실패한다.

해결 방법: response를 우선 반환하도록 `p.done` 분기를 조정한다. 예를 들어 `p.done`을 받았을 때 pending response channel을 비차단으로 한 번 확인하고, response가 있으면 error 처리 규칙까지 동일하게 적용해 반환한다. 더 나은 구조가 있으면 적용하되 pending map 삭제와 context cancel 동작은 유지한다.

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

테스트 작성:
- [ ] process stdout close와 response delivery가 붙어 있어도 response가 우선 처리되는 회귀 테스트를 안정화한다.

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

### [REVIEW_API-2] `thread/start` thread id 필수 검증
문제: `codexAppServerInit`이 `threadId`와 `id`를 모두 찾지 못해도 빈 string을 성공으로 반환한다. 이후 session에는 빈 `threadID`가 저장되어 후속 turn 실행이 올바른 thread에 붙을 수 없다.

해결 방법: `thread/start` 응답에서 `threadId` 또는 fallback `id`가 비어 있으면 명시적 error를 반환한다. error 메시지는 response shape를 진단할 수 있도록 `thread/start`와 thread id 누락을 포함한다.

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

테스트 작성:
- [ ] `thread/start` 응답에 thread id가 없을 때 `codexAppServerInit`이 error를 반환하는 테스트를 추가한다.
- [ ] 기존 `threadId`와 fallback `id` 성공 경로가 유지되는지 확인한다.

중간 검증:
```bash
go test ./apps/node/internal/adapters/cli -run 'TestCodexAppServerRPC|TestCodexAppServerThread' -count=1 -timeout=30s
```

## 범위 결정 근거
라우터 등록, session reporter 연결, legacy persistent startup 제외는 첫 리뷰에서 Required로 지적되지 않았다. 이번 follow-up은 실패 재현 가능한 RPC lifecycle 이슈와 thread id 계약 보완만 다룬다.

## 리뷰어를 위한 체크포인트
- `send`가 이미 dispatch된 response를 process-exit보다 우선 처리하는지 확인한다.
- `pending` cleanup, context cancel, duplicate close 동작이 깨지지 않았는지 확인한다.
- `thread/start` 응답의 thread id 누락이 성공으로 묻히지 않는지 확인한다.
- 구현자가 기록한 검증 출력이 실제 명령과 일치하는지 확인한다.

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

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