<!-- task=m-product-baseline/01_shell_nav_status plan=0 tag=SHELL_NAV -->

# Plan - SHELL_NAV

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

`CODE_REVIEW-local-G05.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 필수 마지막 단계다. 구현 후 검증을 실행하고 실제 변경 내용, 검증 출력, 계획 대비 변경 사항을 기록한 뒤 active 파일을 그대로 둔 채 리뷰 준비를 보고한다. 사용자만 결정할 수 있는 차단, 사용자 소유 외부 환경, 범위 충돌이 생기면 리뷰 stub의 `사용자 리뷰 요청` 섹션에 근거를 남기고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다.

## 배경

현재 Milestone의 첫 Epic은 macOS 업무 앱으로서 기본 shell이 안정적으로 동작하는지 고정하는 작업이다. 기존 shell은 좌측 rail과 상단 Jenkins/ADB pill을 갖고 있지만 navigation 전환 검증은 일부 화면에만 걸려 있다. 실제 Jenkins/ADB 상태 연결 전에도 사용자가 진입 지점을 놓치지 않도록 shell 상태 영역과 전환 테스트를 먼저 고정한다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active `CODE_REVIEW-local-G05.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 prompt는 금지이며, code-review가 요청의 정당성을 판단하고 필요한 경우에만 `USER_REVIEW.md`를 작성한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/usable-mvp/milestones/product-baseline.md`
- Task ids:
  - `nav-shell`: 좌측 navigation과 상단 Jenkins/ADB 상태 영역을 실제 상태 연결 전에도 안정적으로 표시한다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/usable-mvp/PHASE.md`
- `agent-roadmap/phase/usable-mvp/milestones/product-baseline.md`
- `agent-ops/rules/project/domain/app-shell/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/app-shell-smoke.md`
- `analysis_options.yaml`
- `pubspec.yaml`
- `lib/main.dart`
- `lib/src/app.dart`
- `lib/src/features/app_shell.dart`
- `lib/src/features/builds/builds_page.dart`
- `lib/src/features/devices/devices_page.dart`
- `lib/src/features/console/console_page.dart`
- `lib/src/features/settings/settings_page.dart`
- `lib/src/theme/app_theme.dart`
- `test/widget_test.dart`

### 테스트 환경 규칙

- `test_env=local`.
- `agent-test/local/rules.md`를 읽었다.
- 매칭 profile은 `agent-test/local/app-shell-smoke.md`.
- 필수 검증은 remote Mac runner checkout에서 `flutter analyze`와 `flutter test`.
- 현재 checkout preflight로도 같은 명령을 사용할 수 있지만, 최종 완료 evidence는 remote runner 기준이다.
- `<확인 필요>` 값은 없다.

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

- navigation initial render: 기존 `test/widget_test.dart`가 `AppSok`, `빌드`, `디바이스`, `콘솔`, `설정` 표시를 일부 확인한다.
- navigation 전환: 기존 테스트는 `디바이스` 전환만 확인하고, `콘솔`, `설정`, 다시 `빌드` 전환은 확인하지 않는다.
- top Jenkins/ADB status: 기존 테스트가 `Jenkins 대기`, `ADB 대기` pill 표시를 직접 확인하지 않는다.

### 심볼 참조

- none. 이름 변경이나 제거 계획은 없다.

### 분할 판단

- split decision policy를 먼저 평가했다.
- 공유 task group은 `agent-task/m-product-baseline/`.
- `01_shell_nav_status`: navigation/status 구조와 전환 테스트를 고정한다. 선행 의존 없음.
- `02+01_responsive_ui`: responsive overflow 대응이며 `01_shell_nav_status`의 shell 구조가 먼저 안정화된 뒤 구현해야 한다.
- 이 plan은 `01_shell_nav_status`만 다룬다.

### 범위 결정 근거

- Jenkins API, Keychain, ADB process 호출은 app-shell domain 금지 사항이므로 제외한다.
- `BuildsPage`, `DevicesPage`, `ConsolePage`, `SettingsPage`의 실제 feature 동작 구현은 후속 Milestone 소관이므로 제외한다.
- responsive overflow 대응은 `02+01_responsive_ui` plan으로 분리한다.

### 빌드 등급

- `local-G05`: app-shell 내부와 widget test에 한정되고 검증 명령이 결정적이지만, UI shell 상태와 roadmap completion anchor가 있어 중간 등급으로 둔다.

## 구현 체크리스트

- [ ] 좌측 navigation destination 4개와 상단 `Jenkins 대기`/`ADB 대기` 상태 pill이 실제 상태 연결 전에도 안정적으로 렌더링되도록 `AppSokShell` 구조를 정리한다. 검증: `flutter test`에서 app shell 렌더링과 navigation 전환이 통과한다.
- [ ] `test/widget_test.dart`에 빌드, 디바이스, 콘솔, 설정 전환 및 top status 표시 assertion을 추가한다.
- [ ] `dart format lib/src/features/app_shell.dart test/widget_test.dart`를 실행한다.
- [ ] `flutter analyze`와 `flutter test`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [SHELL_NAV-1] Shell navigation/status baseline

#### 문제

- `lib/src/features/app_shell.dart:53`-`76`에서 좌측 rail은 존재하지만, 테스트가 모든 destination 전환을 고정하지 않는다.
- `lib/src/features/app_shell.dart:151`-`162`의 top bar status pill은 `Jenkins 대기`, `ADB 대기`로 hard-coded 되어 있으나 `test/widget_test.dart:19`-`35`에서 표시 여부를 직접 검증하지 않는다.

#### 해결 방법

현재 shell ownership 안에서 route wiring과 표시 안정성만 다룬다. 필요하면 status pill에 안정적인 key/tooltip을 추가하고, navigation label과 title이 destination 변경에 맞춰 유지되도록 정리한다.

Before:

```dart
// lib/src/features/app_shell.dart:151
return SizedBox(
  height: 72,
  child: Padding(
    padding: const EdgeInsets.symmetric(horizontal: 28),
    child: Row(
      children: [
        Text(title, style: Theme.of(context).textTheme.titleLarge),
        const Spacer(),
        const _StatusPill(icon: Icons.key_outlined, label: 'Jenkins 대기'),
        const SizedBox(width: 8),
        const _StatusPill(icon: Icons.usb_outlined, label: 'ADB 대기'),
      ],
    ),
  ),
);
```

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

- [ ] `lib/src/features/app_shell.dart`: shell status 표시가 테스트에서 안정적으로 찾을 수 있는 구조인지 확인하고 필요 시 key/tooltip을 추가한다.
- [ ] `test/widget_test.dart`: 모든 shell destination 전환과 `Jenkins 대기`, `ADB 대기` 표시를 검증한다.

#### 테스트 작성

- 작성한다.
- 경로: `test/widget_test.dart`
- 테스트명 후보: `switches between all shell destinations`, `shows shell status placeholders`
- assertion 목표: 각 navigation label tap 후 해당 page의 대표 텍스트 또는 title이 표시되고 top status pill 2개가 렌더링된다.

#### 중간 검증

```bash
flutter test
```

기대 결과: 모든 widget test가 통과한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `lib/src/features/app_shell.dart` | SHELL_NAV-1 |
| `test/widget_test.dart` | SHELL_NAV-1 |

## 최종 검증

```bash
dart format lib/src/features/app_shell.dart test/widget_test.dart
flutter analyze
flutter test
```

Remote Mac runner 최종 evidence:

```bash
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter analyze'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter test'
```

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