<!-- task=m-openai-workspace-agent-execution-contract/05_failure_surface plan=2 tag=REVIEW_REVIEW_FAILURE_SURFACE -->

# Plan - REVIEW_REVIEW_FAILURE_SURFACE

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

`CODE_REVIEW-local-G08.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 필수 마지막 단계다. 검증을 실행하고 실제 출력과 구현 메모를 기록한 뒤 active 파일을 그대로 두고 리뷰 준비 상태로 보고한다. 사용자 결정, 사용자 소유 외부 환경, 또는 범위 충돌 없이는 진행할 수 없을 때만 review stub의 `사용자 리뷰 요청` 섹션에 증거와 재개 조건을 기록하고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review-skill 전용이다.

## 배경

G07 구현은 pre-start error를 `RuntimeEvent{Type: error}`로 emit하도록 코드를 보강했다. 그러나 새 regression 중 `ExecuteCodexAppServer`와 `ExecuteOpencodeSSE`는 profile `Mode`를 지정하지 않아 실제 specialized executor가 아니라 기본 persistent executor를 타고 있다. 따라서 specialized launch path의 error-event propagation을 테스트로 잠그지 못한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/openai-workspace-agent-execution-contract.md`
- Task ids:
  - `failure-surface`: workspace 누락, 존재하지 않는 경로, 권한 오류, agent process exit failure가 호출자에게 구분 가능한 실패로 드러난다.
- Completion mode: check-on-pass

## 리뷰 근거

- Archived plan: `agent-task/m-openai-workspace-agent-execution-contract/05_failure_surface/plan_local_G07_1.log`
- Archived review: `agent-task/m-openai-workspace-agent-execution-contract/05_failure_surface/code_review_local_G07_1.log`
- Required issue: `apps/node/internal/adapters/cli/cli_internal_test.go`의 codex/opencode workspace preflight tests가 `Mode` 없이 작성되어 `executorFor`에서 specialized executor로 라우팅되지 않는다.

## 범위 결정 근거

- G07의 production code 변경은 계획한 error-event propagation 구조를 갖추고 있으므로 이 follow-up은 테스트 의미 보강에 집중한다.
- 외부 `codex`/`opencode` binary를 실제 실행하지 않는다. nonexistent workspace preflight가 command start 전에 실패하도록 유지한다.
- Edge HTTP missing/relative workspace validation, Node transport protocol, roadmap 문서는 수정하지 않는다.

## 빌드 등급

- `local-G08`: 명시적이고 deterministic한 테스트 라우팅 보강이다. 변경 범위가 작고 로컬 Go test로 판정 가능하다.

## 구현 체크리스트

- [ ] [REVIEW_REVIEW_FAILURE_SURFACE-1] codex-app-server/opencode-sse bad workspace tests가 실제 specialized executor를 타도록 `Mode`와 assertion을 보강한다.
- [ ] `go test -count=1 ./apps/node/internal/adapters/cli ./apps/edge/internal/openai`와 `go test -count=1 ./apps/node/... ./apps/edge/...`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

이 follow-up은 같은 split subtask의 두 번째 후속 루프이며 새 runtime predecessor는 없다. 구현 순서는 test profile mode 수정, specialized wrapper assertion 추가, 검증 실행 순서다.

### [REVIEW_REVIEW_FAILURE_SURFACE-1] Specialized Mode Test Routing

#### 문제

`apps/node/internal/adapters/cli/cli_internal_test.go`의 `ExecuteCodexAppServer`와 `ExecuteOpencodeSSE` subtests는 `Persistent: true`와 args만 지정한다. `executorFor`는 args가 아니라 `profile.Mode`로 specialized executor를 선택하므로, 현재 테스트는 각각 `codexAppServerExecutor`와 `opencodeExecutor`를 타지 않는다.

#### 해결 방법

각 profile에 mode를 명시한다.

```go
"codex-app": {
    Mode:       modeCodexAppServer,
    Command:    "codex",
    Persistent: true,
    Args:       []string{"--app-server"},
}

"opencode-sse-target": {
    Mode:       modeOpencodeSSE,
    Command:    "opencode",
    Persistent: true,
    Args:       []string{"serve"},
}
```

nonexistent workspace를 유지하면 helper가 command start 전에 실패하므로 외부 CLI 설치 여부와 무관하게 deterministic하다.

Assertion은 단순 `workspace not found`뿐 아니라 specialized wrapper도 확인한다.

- codex: `start codex app-server`와 `workspace not found`
- opencode: `start opencode server`와 `workspace not found`

returned error와 sink `EventTypeError` 모두 같은 조건을 만족해야 한다.

#### 수정 파일 및 체크리스트

- [ ] `apps/node/internal/adapters/cli/cli_internal_test.go`: codex-app-server test profile에 `Mode: modeCodexAppServer`를 추가한다.
- [ ] `apps/node/internal/adapters/cli/cli_internal_test.go`: opencode-sse test profile에 `Mode: modeOpencodeSSE`를 추가한다.
- [ ] `apps/node/internal/adapters/cli/cli_internal_test.go`: returned error와 `EventTypeError.Error`가 specialized wrapper와 workspace classification을 모두 포함하는지 검증한다.

#### 테스트 작성

테스트 작성: yes. 이번 follow-up 자체가 테스트 의미 보강이다.

#### 중간 검증

```bash
go test -count=1 ./apps/node/internal/adapters/cli
```

기대 결과: bad workspace tests가 specialized mode에서도 외부 binary 실행 없이 preflight error event를 검증하고, 기존 cwd/session/process-exit tests가 통과한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/node/internal/adapters/cli/cli_internal_test.go` | REVIEW_REVIEW_FAILURE_SURFACE-1 |

## 최종 검증

```bash
go test -count=1 ./apps/node/internal/adapters/cli ./apps/edge/internal/openai
go test -count=1 ./apps/node/... ./apps/edge/...
git diff --check
```

기대 결과: 모든 명령이 0 exit. Go test cache output은 허용하지 않는다. `git diff --check` output은 없어야 한다.

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