<!-- task=cli_real_e2e_failures/01_claude_tui plan=0 tag=CTUI -->

# PLAN-cloud-G07 - claude-tui real e2e failure

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

실제 `bin/edge.sh` + `bin/node.sh` 사용자 흐름에서 `claude-tui` 첫 메시지가 실패했다. 일반 단위 테스트의 가짜 TUI 성공 여부가 아니라, 실제 CLI profile이 edge 명령으로 메시지 2번을 주고받는지까지 복구해야 한다.

최종 산출물은 원인 분석에 필요한 오류 진단 보강, 최소 수정, 회귀 테스트, 실제 e2e 재검증이다. 불확실한 부분은 단정하지 말고 진단 로그를 근거로 후보를 좁힌 뒤 수정한다.

## 배경

- 실행 일자: 2026-05-22
- 실제 e2e 로그 루트: `/tmp/iop-real-cli-e2e-UCUE1C`
- 실패 profile: `claude-tui`
- 실패 흐름:
  - `bin/node.sh --config <temp-config>`
  - `bin/edge.sh --config <temp-config>`
  - `/nodes`, `/capabilities node0`, `/transport node0` 정상
  - 첫 메시지 전송 후 `[node0-evt] start`
  - 곧바로 `[node0-evt] error ... detail="persistent session process exited: exit status 1"`
  - non-empty `[node0-msg]` 없음

같은 실행에서 `claude`, `antigravity`, `codex`는 메시지 2회 실제 흐름을 통과했다. 따라서 우선 범위는 `claude-tui` persistent terminal path와 해당 profile 설정으로 제한한다.

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/rules/domain/node/rules.md`
- `agent-ops/rules/domain/edge/rules.md`
- `agent-ops/rules/domain/testing/rules.md`
- `configs/edge.yaml`
- `apps/node/internal/adapters/cli/cli.go`
- `apps/node/internal/adapters/cli/persistent.go`
- `apps/node/internal/adapters/cli/persistent_output_filter.go`
- `apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go`
- `apps/node/internal/adapters/cli/persistent_output_filter_test.go`
- `apps/node/internal/adapters/cli/lifecycle_blackbox_test.go`

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

- `persistent_execute_blackbox_test.go:66`의 process exit 테스트는 error event 존재만 확인하고, child stdout/stderr 또는 최근 terminal output이 error detail에 포함되는지는 확인하지 않는다.
- `persistent_execute_blackbox_test.go:430` 이후의 `claude-tui` 테스트들은 가짜 terminal chrome/filter 성공을 검증하지만, 실제 `claude` 바이너리와 `configs/edge.yaml:75`의 `claude-tui` profile을 통과시키지 않는다.
- `lifecycle_blackbox_test.go:137`은 `persistent-lazy` 세션 생성 흐름을 검증하지만, lazy terminal profile이 첫 입력 직후 종료될 때 원인 진단을 보존하는 회귀 테스트가 없다.

### 심볼 참조

- `configs/edge.yaml:75` - `claude-tui` profile. `command: claude`, `terminal: true`, `mode: persistent-lazy`, `startup_idle_timeout_ms: 4000`.
- `apps/node/internal/adapters/cli/persistent.go:84` - target/profile 기준 output filter 생성.
- `apps/node/internal/adapters/cli/persistent.go:94` - terminal prompt 입력.
- `apps/node/internal/adapters/cli/persistent.go:120` - output channel closed 시 generic `persistent session process exited unexpectedly` 반환.
- `apps/node/internal/adapters/cli/persistent.go:205` - `sess.done` 종료 시 `persistent session process exited: exit status 1`만 runtime error로 전파.
- `apps/node/internal/adapters/cli/persistent.go:291` - terminal startup drain에서 Claude bypass warning 자동 수락.
- `apps/node/internal/adapters/cli/cli.go:267` - `TerminateSession`의 persistent session cleanup.

### 분할 판단

`claude-tui` 실패는 terminal persistent process lifecycle 문제이고, `opencode` 실패는 HTTP/SSE session 재사용 문제다. 수정 파일 일부가 같은 package에 있어도 원인, 재현, 검증 경로가 달라 서로 독립 plan으로 분리한다.

### 범위 결정 근거

이 plan은 `claude-tui`만 다룬다. `claude` one-shot, `antigravity`, `codex`, `opencode` 동작 변경은 금지한다. 공통 persistent 함수 수정이 필요하면 기존 fake shell 테스트로 다른 persistent profile의 회귀가 없음을 확인한다.

### 빌드 등급

- Lane: `cloud`
- Grade: `G07`
- 근거: 실제 외부 CLI와 `bin/edge.sh`/`bin/node.sh` 사용자 흐름에서만 드러난 실패이며, 단위 테스트만으로 완료 판정할 수 없다.

## 구현 체크리스트

- [ ] `claude-tui` process exit error에 child stderr/stdout/최근 terminal output tail이 포함되도록 진단을 보강한다.
- [ ] 보강된 진단으로 실제 실패 원인을 재현하고, `claude-tui` profile 또는 persistent terminal handling 중 최소 위치를 수정한다.
- [ ] 같은 session에서 메시지 2번이 complete되는 회귀 테스트를 추가하거나 기존 테스트를 강화한다.
- [ ] 실제 `bin/edge.sh` + `bin/node.sh` 흐름으로 `claude-tui` 메시지 2회를 재검증한다.
- [ ] `CODE_REVIEW-cloud-G07.md`를 구현 결과 기준으로 갱신한다.

## 구현 계획

### [CTUI-1] persistent terminal exit 진단을 보존한다

문제:

- 현재 실패 로그는 `persistent session process exited: exit status 1`뿐이라 실제 `claude`가 왜 종료됐는지 알 수 없다.
- terminal profile은 PTY stdout/stderr가 같은 stream으로 들어오지만, `persistent.go:205`의 `sess.done` 경로가 최근 출력 tail을 보존하지 않는다.

수정 방향:

- `profileSession`에 bounded output tail 또는 exit diagnostic buffer를 추가한다.
- PTY read loop와 non-terminal scanner loop에서 output을 `appendBounded` 방식으로 보존한다.
- `persistent.go:120`과 `persistent.go:205` 종료 경로에서 `target`, `session`, command/args 요약, exit error, 최근 output tail을 포함한 error detail을 만든다.
- tail은 민감정보 노출을 줄이기 위해 크기를 제한하고, 빈 tail이면 기존 메시지와 호환되게 둔다.

예상 수정 파일:

- `apps/node/internal/adapters/cli/persistent.go`
- `apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go`
- 필요 시 `apps/node/internal/adapters/cli/lifecycle_blackbox_test.go`

테스트:

- `exit-on-input`류 fake terminal이 `before-exit`를 출력하고 종료할 때 runtime error event가 해당 tail을 포함하는지 확인한다.
- startup 중 즉시 종료하는 profile도 stderr/stdout tail을 보존하는 회귀 테스트를 추가한다.

### [CTUI-2] 실제 claude-tui 첫/두 번째 메시지 실패 원인을 수정한다

문제:

- 실제 profile은 `configs/edge.yaml:75`에서 terminal persistent-lazy로 설정되어 있다.
- 실제 실행에서 startup command는 등록되고 `/transport`까지 응답했지만 첫 prompt 후 process가 종료됐다.
- 단정 가능한 사실은 "프로세스가 exit 1로 종료됐다"까지다. 원인 후보는 Claude TUI 실행 조건, permission warning 처리, prompt 입력 방식, 또는 profile args 불일치다.

수정 방향:

- CTUI-1 적용 후 같은 실제 e2e를 다시 실행해 `claude-tui` 종료 tail을 확보한다.
- tail이 CLI usage/config 오류를 가리키면 `configs/edge.yaml:75` profile args/env를 최소 수정한다.
- tail이 interactive warning/selector를 가리키면 `drainUntilIdle`의 Claude terminal startup handling을 보강한다.
- tail이 prompt 입력 후 TUI가 request/response adapter로 유지될 수 없음을 가리키면 `claude-tui` profile을 지원 가능한 mode로 바꾸는 방안을 후보로 남기고 사용자 확인을 받은 뒤 진행한다.

예상 수정 파일:

- `configs/edge.yaml`
- `apps/node/internal/adapters/cli/persistent.go`
- `apps/node/internal/adapters/cli/persistent_output_filter.go`
- 관련 blackbox test 파일

검증:

- `go test ./apps/node/internal/adapters/cli -run 'Persistent|ClaudeTUI|Lifecycle'`
- 실제 사용자 흐름:
  - `bin/node.sh --config <temp-config>`
  - `bin/edge.sh --config <temp-config>`
  - `/nodes`
  - `/capabilities node0`
  - `/transport node0`
  - `node0`에 `IOP_E2E_CLAUDE_TUI_ONE` 정확 응답 요청
  - 같은 session에서 `IOP_E2E_CLAUDE_TUI_TWO` 정확 응답 요청
  - 두 번 모두 non-empty `[node0-msg]`와 complete 확인

## 수정 파일 요약

| 파일 | 수정 의도 |
| --- | --- |
| `apps/node/internal/adapters/cli/persistent.go` | persistent terminal 종료 진단 보존 및 필요 시 Claude TUI lifecycle 보정 |
| `apps/node/internal/adapters/cli/persistent_execute_blackbox_test.go` | 종료 진단과 `claude-tui` 2회 메시지 회귀 테스트 |
| `apps/node/internal/adapters/cli/lifecycle_blackbox_test.go` | lazy terminal startup/exit 회귀 테스트 필요 시 보강 |
| `configs/edge.yaml` | 실제 `claude-tui` profile args/env/mode 최소 수정 필요 시 반영 |
| `agent-task/cli_real_e2e_failures/01_claude_tui/CODE_REVIEW-cloud-G07.md` | 구현 후 review 기준 갱신 |

## 최종 검증

- `go test ./apps/node/internal/adapters/cli -run 'Persistent|ClaudeTUI|Lifecycle'`
- `go test ./apps/node/internal/adapters/cli`
- 실제 `claude-tui` e2e 사용자 흐름 2회 메시지 통과 로그 첨부

최종 응답에는 수정 파일, 테스트 명령, 실제 e2e 로그 위치, 남은 위험을 요약한다.
