## 2026-04-18 — PTY 어댑터화(Gemini/Codex 대화 수정) + Todo UI 롤백

### 배경

Gemini TUI는 `\r\n`을 Enter로 인식하고, Claude/Codex는 `\r`만으로 입력이 제출됨. 기존 하드코딩 `\r` 치환으로 인해 Gemini 인터랙티브 모드에서 사용자 메시지가 제출되지 않고 입력창에 누적되던 버그를 어댑터별 PTY submit sequence 분리로 해결. 또한 4/16에 적용한 TodoItem CMD/터미널 스타일이 앱 전반과 이질적이라는 피드백에 따라 일반 카드 UI로 복구(터미널 스타일은 실제 CLI 스트림이 있는 영역에만 유지).

### 주요 변경

#### 1. PTY submit sequence를 어댑터별로 분리 (`69395e1`)

- **서버**: `cli-adapters.ts` — `CliAdapter.stdinSubmitSequence` 필드 추가 (기본 `\r`, Gemini만 `\r\n` 오버라이드)
- **서버**: `claude-manager.ts` — 모든 PTY write 경로(초기 프롬프트 즉시/지연 전달, WebSocket stdin relay, 5s delayStdin fallback)에서 어댑터의 submit sequence 사용

#### 2. CLI trust/update 프롬프트 자동 응답을 어댑터 레벨로 일반화 (`bfe3d29`)

- **서버**: `cli-adapters.ts` — `delayStdinUntilReady`, `readyIndicatorPattern`, `AutoRespondRule[]` (blocking/non-blocking) 추가
  - Claude: 기존 trust-Enter 규칙을 새 형식으로 포팅
  - Gemini: welcome-screen ready 패턴, "Trust folder" 자동 확인(`1\r` 전송), 업데이트 프롬프트 거부 규칙 추가. 첫 실행 시 trust 다이얼로그가 사용자 초기 프롬프트를 삼키던 문제 해결
  - Codex: TUI 커서 ready 패턴 기반 delayStdin 활성화 (rule 목록은 placeholder)
- **서버**: `claude-manager.ts` — Claude 전용 trust regex 블록을 `adapter.autoRespondRules` 순회로 치환, trust clear 시 `stdinDelivered` 리셋(Gemini의 trust 승인 후 in-process restart 대응)

#### 3. Codex/Gemini 세션 재개 + Interactive 모드 복구 (`13979fb`)

- **서버**: `cli-adapters.ts` — Codex 어댑터가 `continueSession` 시 `exec resume --last` 발행, interactive 모드에서는 `exec` 서브커맨드 생략하고 top-level `codex` TUI 기동
- **서버**: `cli-adapters.ts` — Gemini 어댑터가 `continueSession` 시 `--resume latest` 발행
- **서버**: `claude-manager.ts` — PTY 분기 조건을 Claude 전용에서 interactive 모드 전체로 확대 (Codex/Gemini interactive 세션이 pipe 대신 진짜 TTY 획득)
- **테스트**: Codex resume, Gemini resume, Codex interactive args에서 `exec` 제외 케이스 커버리지 추가

#### 4. TodoItem 확장 섹션 UI 롤백 — 터미널 스타일 → 일반 카드 UI (`cc0f502`)

- **클라이언트**: `TodoItem.tsx` — 4/16의 CMD/터미널 래퍼(트래픽 라이트, `$ cat task.md` 등)를 제거하고 설명/브랜치/결과/diff 섹션을 Tailwind 카드/라벨/리스트로 재작성
- **클라이언트**: 터미널 스타일은 실제 CLI 스트림이 있는 영역에만 유지 — `$ tail -f task.log` LogViewer 래퍼, FAILED 에러 블록
- **클라이언트**: 결과 섹션에 stats chips(duration/commits/files/tokens) + 커밋 리스트 + 변경 파일 리스트(상태별 컬러 뱃지)
- **클라이언트**: 액션 에러 메시지를 CMD inline 문자열에서 status-error chip 카드로 변경
- **i18n**: `todo.worktree`, `todo.result` 키 추가

#### 5. 더 보기 메뉴에서 Diff 클릭 시 자동 확장 (`0114bfe`)

- **클라이언트**: `TodoItem.tsx` — `handleViewDiff`가 성공/실패 모두에서 `setExpanded(true)` 호출 (접힌 상태에서 더 보기 메뉴로 Diff 트리거 시 결과가 보이지 않던 버그 수정)

### 수정된 주요 파일

| 파일 | 변경 내용 |
|------|----------|
| `src/server/services/cli-adapters.ts` | `stdinSubmitSequence`, `delayStdinUntilReady`, `readyIndicatorPattern`, `autoRespondRules` 추가; Codex/Gemini resume 및 interactive args 분기 |
| `src/server/services/claude-manager.ts` | 어댑터 기반 PTY submit/autoRespond 루프, interactive 모드 PTY 확장 |
| `src/client/src/components/TodoItem.tsx` | 확장 섹션 카드형 UI 복원, Diff 클릭 자동 확장 |
| `src/server/services/__tests__/cli-adapters.test.ts` | Codex/Gemini resume·interactive 테스트 추가 |

### 아키텍처 결정

1. **PTY 입력 시퀀스 어댑터화**: 기존 Claude 기준 하드코딩을 제거하고 어댑터가 "CLI의 TUI가 기대하는 Enter 문자"를 선언하도록 변경. Gemini(`\r\n`), Claude/Codex(`\r`) 등 CLI별 차이를 adapter.ts 하나에 격리
2. **Auto-respond 규칙 일반화**: trust/update 프롬프트 자동 응답을 Claude 전용 분기에서 `AutoRespondRule[]` 배열로 일반화하여 신규 CLI 추가 시 규칙만 선언하면 되는 구조. blocking 규칙은 초기 프롬프트를 gating, non-blocking 규칙은 중간에 삽입되는 다이얼로그에 응답
3. **Todo 확장 UI 카드 복귀**: 전체 앱 톤과 이질적인 터미널 래퍼를 제거하되 실제 로그 스트림이 있는 영역에만 CMD 스타일 유지. "정보 패널"과 "터미널 스트림"을 시각적으로 구분

---
