<!-- task=m-agent-readable-repository-refactor/08_adapter_cli_tests plan=0 tag=TEST -->

# CLI adapter 테스트 실행 모드별 분해

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

> 구현 후 계획의 검증 명령을 그대로 실행하고 CODE_REVIEW의 구현 에이전트 소유 섹션에 실제 메모와 stdout/stderr를 채운 뒤 active 파일을 유지한 채 리뷰 준비 완료를 보고한다. 종결 판정, log rename, complete.log와 archive 이동은 code-review 전용이다. 선택된 Milestone의 미해결 구현 잠금 결정이 실제 구현을 차단할 때만 review stub의 사용자 리뷰 요청에 연결 근거를 기록하고 중단한다. 직접 사용자 질문, chat 선택지, request_user_input, USER_REVIEW.md/complete.log 작성은 금지한다. 환경·secret·service, 일반 범위 조정, 후속으로 보완 가능한 증거 공백은 사용자 리뷰 사유가 아니다.

## 배경

CLI adapter에는 1,110~1,462줄의 세 test 파일이 emitter/session, persistent PTY, Codex app-server 책임을 다시 혼합한다. terminal semantics를 바꾸지 않고 mode/session/event 책임별 파일로 재배치한다.

## 사용자 리뷰 요청 흐름

사용자 리뷰 요청은 선택된 Milestone의 구현 잠금 결정만 active review stub의 사용자 리뷰 요청 섹션에 agent-ops/skills/common/_templates/implementation-user-review-request-section.md 형식으로 기록한다. 구현 중 직접 사용자 prompt는 금지하며, 타당성 검증과 USER_REVIEW.md 작성은 code-review가 소유한다.

## 분석 결과

### 읽은 파일

- agent-roadmap/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md
- agent-test/local/rules.md
- agent-test/local/profiles/node-smoke.md
- agent-spec/runtime/edge-node-execution.md
- apps/node/internal/adapters/cli/cli_internal_test.go
- apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go
- apps/node/internal/adapters/cli/codex_app_server_internal_test.go

### SDD 기준

선택 Milestone은 SDD: 불필요다. 외부 API/proto/config schema와 runtime 책임 경계를 바꾸지 않는 동작 보존형 테스트 재배치라는 기록 사유를 적용한다.

### 테스트 환경 규칙

test_env=local. local rules와 node-smoke profile을 읽었다. 현재 checkout에서 fresh CLI package test가 46.960초에 통과했고 Test 목록은 173개다. PTY test이므로 2분 무진행 시 blind retry를 중단하고 focused -run 출력과 환경 근거를 남긴다.

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

동작 변경은 없다. 기존 173개 Test의 PTY timing, helper process, emitter assertion을 그대로 이동한다.

### 심볼 참조

운영 심볼의 rename/remove는 없다. 기존 Test* 이름과 package 경계를 유지한다.

### 분할 판단

CLI/PTY는 openai_compat HTTP adapter와 risk/verification이 달라 독립 08 plan이다. 07,08,09는 병렬 가능하고 10+07,08,09가 최종 adapter-command-tests를 완료한다.

### 범위 결정 근거

세 1,000줄 이상 CLI test 파일과 test-only helper만 수정한다. process/session production code, timeout 값, terminal behavior는 제외한다.

### 빌드 등급

local-G08: 4,000줄 가까운 PTY/helper-process test를 여러 책임으로 옮기며 import와 helper 가시성 보존이 중요하다.

## 구현 체크리스트

- [x] [TEST-1] CLI emitter/session, persistent PTY, Codex app-server 테스트를 실행 모드별 파일로 옮기고 Test 173개와 fresh package test를 보존한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [TEST-1] CLI/PTY/Codex app-server 테스트 분리

- 문제: cli_internal_test.go:41, persistent_execute_blackbox_test.go:21, codex_app_server_internal_test.go:33부터 서로 다른 실행 모드와 helper가 각각 대형 파일에 혼합되어 있다.
- 해결 방법:

~~~text
Before
cli_internal_test.go:41 func TestDriveJSONLines_DispatchesEmitterEvents(...)
persistent_execute_blackbox_test.go:21 func TestCLIExecutePersistentWaitsForSlowFirstOutput(...)
codex_app_server_internal_test.go:33 func TestCodexAppServerSessionResolve(...)

After
cli_test_support_test.go
cli_emitters_test.go
cli_session_test.go
cli_workspace_test.go
persistent_process_test.go
persistent_terminal_test.go
persistent_completion_test.go
codex_app_server_session_test.go
codex_app_server_events_test.go
~~~

- 수정 파일 및 체크리스트:
  - [x] apps/node/internal/adapters/cli/cli_internal_test.go: 이동 후 삭제한다.
  - [x] apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go: 이동 후 삭제한다.
  - [x] apps/node/internal/adapters/cli/codex_app_server_internal_test.go: 이동 후 삭제한다.
  - [x] apps/node/internal/adapters/cli/cli_test_support_test.go: helper process와 공통 fixture를 둔다.
  - [x] apps/node/internal/adapters/cli/cli_emitters_test.go: JSON emitter/driver를 둔다.
  - [x] apps/node/internal/adapters/cli/cli_session_test.go: session list/terminate를 둔다.
  - [x] apps/node/internal/adapters/cli/cli_workspace_test.go: cwd/preflight를 둔다.
  - [x] apps/node/internal/adapters/cli/persistent_process_test.go: non-terminal persistent를 둔다.
  - [x] apps/node/internal/adapters/cli/persistent_terminal_test.go: PTY/TUI를 둔다.
  - [x] apps/node/internal/adapters/cli/persistent_completion_test.go: cancel/marker/idle을 둔다.
  - [x] apps/node/internal/adapters/cli/codex_app_server_session_test.go: init/thread/turn을 둔다.
  - [x] apps/node/internal/adapters/cli/codex_app_server_events_test.go: event/drain/priority를 둔다.
- 테스트 작성: 추가 테스트는 작성하지 않는다. existing PTY/helper process Test 173개와 timing을 그대로 보존한다.
- 중간 검증:

~~~bash
gofmt -w apps/node/internal/adapters/cli/*_test.go
test ! -e apps/node/internal/adapters/cli/cli_internal_test.go
test ! -e apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go
test ! -e apps/node/internal/adapters/cli/codex_app_server_internal_test.go
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./apps/node/internal/adapters/cli | sed '/^ok[[:space:]]/d' | wc -l)" -eq 173 ]
~~~

기대 결과: 세 원본 삭제, gofmt 성공, Test 173개.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| apps/node/internal/adapters/cli/cli_internal_test.go | TEST-1 |
| apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go | TEST-1 |
| apps/node/internal/adapters/cli/codex_app_server_internal_test.go | TEST-1 |
| apps/node/internal/adapters/cli/cli_*_test.go | TEST-1 |
| apps/node/internal/adapters/cli/persistent_*_test.go | TEST-1 |
| apps/node/internal/adapters/cli/codex_app_server_*_test.go | TEST-1 |

## 최종 검증

~~~bash
GOCACHE=/tmp/iop-go-build-cache go test -count=1 ./apps/node/internal/adapters/cli
[ "$(GOCACHE=/tmp/iop-go-build-cache go test -list '^Test' ./apps/node/internal/adapters/cli | sed '/^ok[[:space:]]/d' | wc -l)" -eq 173 ]
python3 -c "from pathlib import Path; p=Path('apps/node/internal/adapters/cli'); bad=sorted((sum(1 for _ in f.open()),str(f)) for f in p.glob('*_test.go') if sum(1 for _ in f.open())>1000); print(bad); raise SystemExit(bool(bad))"
~~~

기대 결과: fresh CLI test PASS, Test 173개, 1,000줄 초과 test 없음.

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

