<!-- task=m-flutter-console-skeleton/01_preview_flow plan=1 tag=REVIEW_UI -->

# Plan - REVIEW UI Preview Evidence Recovery

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

구현 완료 여부는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션까지 실제 내용과 검증 출력으로 채운 뒤에만 판단한다.
검증을 실행하고 실제 stdout/stderr와 증거 경로를 기록한 뒤 active 파일은 그대로 두고 리뷰 준비를 보고한다.
최종 판정, 로그 아카이브, `complete.log` 작성, task directory archive 이동은 code-review-skill 전용이다.
구현 중 사용자만 결정할 수 있는 항목, 사용자 소유 외부 환경, scope conflict가 있으면 review stub의 `사용자 리뷰 요청` 섹션에 근거를 적고 멈춘다.
구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다.
후속 에이전트가 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md`
- Task ids:
  - `preview-flow`: 원격 preview 명령 `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020` 기준으로 첫 화면이 Core API endpoint와 UI 스켈레톤을 안정적으로 렌더링한다.
- Completion mode: check-on-pass

## Archive Evidence Snapshot

- Current archived plan: `agent-task/m-flutter-console-skeleton/01_preview_flow/plan_cloud_G07_0.log`
- Current archived review: `agent-task/m-flutter-console-skeleton/01_preview_flow/code_review_cloud_G07_0.log`
- Verdict: FAIL
- Required summary:
  - Required 1: `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020` was replaced with `flutter run -d web-server`; reviewer rerun of the Makefile target failed with `No supported devices found with name or id matching 'chrome'`.
  - Required 2: first-screen evidence was replaced with HTML shell and JS asset serving; no screenshot or UI-tree evidence proves `Build Operations Overview` and the Runners/Pipelines/Executions/Artifacts/Settings skeleton rendered in a browser.
- Affected files:
  - `Makefile`
  - `apps/client/lib/src/app/oto_client_app.dart`
  - `apps/client/lib/src/app/core_connection_client.dart`
  - `apps/client/pubspec.yaml`
  - `apps/client/pubspec.lock`
  - `apps/client/test/widget_test.dart`
  - `packages/flutter/oto_console/lib/src/oto_console_contract.dart`
  - `packages/flutter/oto_console/lib/src/oto_console_overview.dart`
  - `packages/flutter/oto_console/lib/src/oto_console_shell.dart`
  - `packages/flutter/oto_console/test/oto_console_test.dart`
- Verification evidence:
  - Core preflight passed: `curl -fsS http://toki-labs.com:18020/healthz && printf '\n' && curl -fsS http://toki-labs.com:18020/readyz && printf '\n'` -> `OK`, `OK`
  - Reviewer rerun passed: `cd apps/client && flutter pub get`
  - Reviewer rerun passed: `cd apps/client && flutter analyze` -> `No issues found!`
  - Reviewer rerun passed: `cd apps/client && flutter test` -> `All tests passed!`
  - Reviewer rerun passed: `cd packages/flutter/oto_console && flutter pub get`
  - Reviewer rerun passed: `cd packages/flutter/oto_console && flutter analyze` -> `No issues found!`
  - Reviewer rerun passed: `cd packages/flutter/oto_console && flutter test` -> `All tests passed!`
  - Reviewer rerun failed as expected in current container: `timeout 45s make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020` -> exit code 2, Chrome device unavailable
- Roadmap/spec carryover:
  - Roadmap target remains `preview-flow`.
  - No Spec Targets.
- Allowed narrow reread paths:
  - `agent-task/m-flutter-console-skeleton/01_preview_flow/plan_cloud_G07_0.log`
  - `agent-task/m-flutter-console-skeleton/01_preview_flow/code_review_cloud_G07_0.log`

## 범위 결정 근거

이 후속 계획은 새 UI 코드 작성이나 refactor를 하지 않는다.
이미 reviewer-run analyzer/test는 통과했으므로, 남은 범위는 Chrome-capable 환경에서 고정 preview 명령과 첫 화면 증거를 수집하는 것이다.
현재 컨테이너처럼 Chrome device가 없으면 같은 실패를 반복하지 말고, `flutter devices`, `command -v google-chrome`, 원격 runner의 `command -v flutter`/Chrome 확인 출력까지 남긴 뒤 사용자 소유 환경 준비가 필요한지 `사용자 리뷰 요청`에 기록한다.

## 구현 체크리스트

- [ ] 원격 Core endpoint preflight로 `http://toki-labs.com:18020/healthz`와 `/readyz`가 HTTP 200 `OK`를 반환하는지 기록한다.
- [ ] Chrome-capable 환경에서 `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020`를 실행하고 `/tmp/oto-client-run-web.log`와 `/tmp/oto-client-run-web.pid`를 남긴다.
- [ ] 실행 중인 Chrome preview에서 첫 화면 screenshot 또는 UI-tree evidence를 수집하고 `OTO_SERVER_HTTP_URL`, `Build Operations Overview`, `Runners`, `Pipelines`, `Executions`, `Artifacts`, `Settings` 확인 결과와 증거 경로를 기록한다.
- [ ] preview 프로세스를 종료하고 cleanup 로그를 기록한다.
- [ ] `apps/client`와 `packages/flutter/oto_console`의 setup/analyze/test 검증을 실행하고 실제 stdout/stderr를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_UI-1] Chrome Preview Command Recovery

문제: 이전 구현은 `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020` 대신 `flutter run -d web-server`를 사용했다. `web-server`는 compile+serve 증거일 뿐 Chrome browser rendering evidence가 아니다.

해결 방법: Chrome-capable local 또는 원격 runner에서 Makefile target을 그대로 실행한다. 원격 wrapper를 쓰더라도 runner 내부에서 실행되는 명령은 `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020`여야 한다.

수정 파일 및 체크리스트:

- [ ] 코드 파일 수정 없음
- [ ] `/tmp/oto-client-run-web.log`에 `flutter run -d chrome` launch evidence 저장
- [ ] `/tmp/oto-client-run-web.pid` 저장

테스트 작성: 작성하지 않는다. 이 항목은 external browser smoke evidence다.

중간 검증:

```bash
bash -lc 'set -euo pipefail; rm -f /tmp/oto-client-run-web.log /tmp/oto-client-run-web.pid; make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020 > /tmp/oto-client-run-web.log 2>&1 & echo $! > /tmp/oto-client-run-web.pid; for i in $(seq 1 60); do if grep -Eq "Flutter run key commands|An Observatory debugger|Debug service listening" /tmp/oto-client-run-web.log; then tail -120 /tmp/oto-client-run-web.log; exit 0; fi; if ! kill -0 "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null; then cat /tmp/oto-client-run-web.log; exit 1; fi; sleep 2; done; tail -160 /tmp/oto-client-run-web.log; exit 1'
```

기대 결과: Chrome preview가 compile/launch되고 log에 launch evidence가 남는다.

### [REVIEW_UI-2] First Screen Evidence Recovery

문제: HTML shell과 JS asset 200 응답은 Flutter first screen rendering을 증명하지 못한다.

해결 방법: preview가 떠 있는 동안 screenshot 또는 UI-tree equivalent를 수집한다. 증거는 `http://toki-labs.com:18020`, `Build Operations Overview`, `Runners`, `Pipelines`, `Executions`, `Artifacts`, `Settings` 확인 결과를 포함해야 한다.

수정 파일 및 체크리스트:

- [ ] 코드 파일 수정 없음
- [ ] screenshot 또는 UI-tree evidence path를 `CODE_REVIEW-cloud-G07.md`에 기록
- [ ] capture 명령과 실제 stdout/stderr를 기록

테스트 작성: 작성하지 않는다. 이 항목은 browser smoke evidence다.

중간 검증:

```bash
bash -lc 'test -f /tmp/oto-client-run-web.pid && kill -0 "$(cat /tmp/oto-client-run-web.pid)" && printf "preview-process=running pid=%s\n" "$(cat /tmp/oto-client-run-web.pid)" && tail -120 /tmp/oto-client-run-web.log'
```

기대 결과: preview process가 살아 있고 screenshot/UI-tree evidence path가 review stub에 기록된다.

### [REVIEW_UI-3] Regression Verification And Cleanup

문제: source/package 변경이 워크트리에 있으므로 preview evidence와 별개로 client와 package 검증 출력도 최신 상태여야 한다.

해결 방법: client와 console package의 setup/analyze/test를 실행하고, preview process를 종료한다.

수정 파일 및 체크리스트:

- [ ] 코드 파일 수정 없음
- [ ] client setup/analyze/test 출력 기록
- [ ] console setup/analyze/test 출력 기록
- [ ] preview process 종료 확인 기록

테스트 작성: 새 테스트 작성 없음.

중간 검증:

```bash
flutter pub get
flutter analyze
flutter test
```

위 세 명령은 각각 `apps/client`, `packages/flutter/oto_console`에서 실행한다.

Cleanup 검증:

```bash
bash -lc 'if test -f /tmp/oto-client-run-web.pid; then kill "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null || true; sleep 2; kill -0 "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null && exit 1 || true; fi; tail -120 /tmp/oto-client-run-web.log'
```

기대 결과: analyzer issue가 없고 모든 테스트가 통과하며 preview process가 종료된다.

## 최종 검증

아래 명령과 증거 수집을 순서대로 실행한다.

```bash
cd /config/workspace/oto && curl -fsS http://toki-labs.com:18020/healthz && printf '\n' && curl -fsS http://toki-labs.com:18020/readyz && printf '\n'
cd /config/workspace/oto/apps/client && flutter pub get && flutter analyze && flutter test
cd /config/workspace/oto/packages/flutter/oto_console && flutter pub get && flutter analyze && flutter test
cd /config/workspace/oto && bash -lc 'set -euo pipefail; rm -f /tmp/oto-client-run-web.log /tmp/oto-client-run-web.pid; make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020 > /tmp/oto-client-run-web.log 2>&1 & echo $! > /tmp/oto-client-run-web.pid; for i in $(seq 1 60); do if grep -Eq "Flutter run key commands|An Observatory debugger|Debug service listening" /tmp/oto-client-run-web.log; then tail -120 /tmp/oto-client-run-web.log; exit 0; fi; if ! kill -0 "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null; then cat /tmp/oto-client-run-web.log; exit 1; fi; sleep 2; done; tail -160 /tmp/oto-client-run-web.log; exit 1'
cd /config/workspace/oto && bash -lc 'test -f /tmp/oto-client-run-web.pid && kill -0 "$(cat /tmp/oto-client-run-web.pid)" && printf "preview-process=running pid=%s\n" "$(cat /tmp/oto-client-run-web.pid)" && tail -120 /tmp/oto-client-run-web.log'
cd /config/workspace/oto && bash -lc 'if test -f /tmp/oto-client-run-web.pid; then kill "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null || true; sleep 2; kill -0 "$(cat /tmp/oto-client-run-web.pid)" 2>/dev/null && exit 1 || true; fi; tail -120 /tmp/oto-client-run-web.log'
```

추가 필수 증거: Chrome preview에서 screenshot 또는 UI-tree evidence path를 기록한다. 이 증거가 없으면 `preview-flow`는 PASS할 수 없다.
