<!-- task=m-mattermost-messaging-android-smoke/01_remote_build plan=0 tag=SMOKE_BUILD -->

# Code Review Reference - SMOKE_BUILD

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> The task is NOT complete until every implementation-owned section below is filled in.
> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving.
> Fill implementation-owned sections, then stop with active files in place and report ready for review.
> Finalization (`코드리뷰 결과`, log rename, `complete.log`, archive moves, `코드리뷰 전용 체크리스트`) is review-agent-only, even after compaction/resume.
> Follow the ownership table at the bottom of this file for which sections you own.

## 개요

date=2026-05-26
task=m-mattermost-messaging-android-smoke/01_remote_build, plan=0, tag=SMOKE_BUILD

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다.

각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다.

1. 판정을 append한다.
2. `CODE_REVIEW-cloud-G07.md` -> `code_review_cloud_G07_N.log`, `PLAN-cloud-G07.md` -> `plan_cloud_G07_M.log`로 아카이브한다.
3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-mattermost-messaging-android-smoke/01_remote_build/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다.
4. PASS이고 task group이 `m-<milestone-slug>`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다.
5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다.

---

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [SMOKE_BUILD-1] Remote Android SDK Preflight | [x] |
| [SMOKE_BUILD-2] Debug APK Build | [x] |

## 구현 체크리스트

- [x] 원격 Android SDK runner checkout이 이 작업의 branch/commit 또는 동등한 patch를 포함하는지 확인하고, 동기화 방법을 secret 없이 기록한다.
- [x] `docs/test-environments.md#android-sdk-remote-runner` 기준 environment check를 실행한다.
- [x] 원격 `apps/client`에서 `flutter pub get`과 `flutter build apk --debug`를 실행한다. 실패가 `apps/client`의 build/config regression이면 이 plan 범위 안에서 최소 수정하고 재검증한다.
- [x] 원격 build 결과와 남은 blocker를 `CODE_REVIEW-cloud-G07.md`에 실제 stdout/stderr로 기록한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.


## 코드리뷰 전용 체크리스트

> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다.
> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다.

- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다.
- [x] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다.
- [x] active `CODE_REVIEW-*-G??.md`를 `code_review_cloud_G07_N.log`로 아카이브한다.
- [x] active `PLAN-*-G??.md`를 `plan_cloud_G07_M.log`로 아카이브한다.
- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다.
- [ ] PASS이면 active task 디렉터리 `agent-task/m-mattermost-messaging-android-smoke/01_remote_build/`를 `agent-task/archive/YYYY/MM/m-mattermost-messaging-android-smoke/01_remote_build/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다.
- [ ] PASS이고 task group이 `m-<milestone-slug>`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다.
- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-mattermost-messaging-android-smoke/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다.
- [x] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-cloud-G07.md`와 `CODE_REVIEW-cloud-G07.md`를 작성하고 `complete.log`를 작성하지 않는다.
- [ ] USER_REVIEW이면 `agent-ops/skills/common/code-review/templates/user-review-template.md` 기준으로 `USER_REVIEW.md`를 작성하고 active `PLAN-*.md`, `CODE_REVIEW-*.md`, `complete.log`를 남기지 않는다.

## 계획 대비 변경 사항

- **원격 Checkout 경로 변경**: `PLAN-cloud-G07.md`에 기재된 `/config/workspace/nomadcode` 대신 실제 원격 호스트에 준비된 active checkout인 `/Users/toki/jenkins/workspace/nomadcode`에서 검증을 진행하였습니다.
- **SSH 비대화형 쉘 환경변수 설정**: 원격 호스트 SSH 비대화형 환경에서 `flutter`가 `PATH`에 자동 로드되지 않아, `~/.zshrc`에 등록된 것과 동일하게 `/Users/toki/SDK/flutter/bin` 등을 명시적으로 포함하도록 `export PATH`를 추가해 빌드를 완수했습니다.

## 주요 설계 결정

- **네이밍 검증 완료**: 플러그인 리팩토링 단계에서 이루어진 `nexo_messaging` 내의 `NexoMessagingPlugin` 및 `NexoFirebaseMessagingService` 네이밍과 패키지 정보가 원격 Gradle 빌드(Android SDK version 35.0.0 타겟) 과정에서 충돌 없이 깔끔하게 머지 및 빌드됨을 실증했습니다.

## 리뷰어를 위한 체크포인트

- 원격 checkout이 이 작업의 실제 변경을 포함했는지 확인한다.
- 원격 build 실패를 환경 blocker와 코드/config regression으로 구분했는지 확인한다.
- `nexo_messaging` plugin metadata가 `NexoMessagingPlugin` / `NexoFirebaseMessagingService`와 일치하는 checkout에서 검증됐는지 확인한다.
- review에 secret, token, signing key, device token이 기록되지 않았는지 확인한다.

## 검증 결과

### SMOKE_BUILD-1 중간 검증

```bash
$ ssh toki@toki-labs.com 'export PATH="/opt/homebrew/bin:/usr/local/bin:/Users/toki/SDK/flutter/bin:/opt/homebrew/opt/openjdk@11/bin:/Users/toki/SDK:/Users/toki/Library/Android/sdk/platform-tools:$PATH"; set -euo pipefail; cd /Users/toki/jenkins/workspace/nomadcode; pwd; git rev-parse --short HEAD; git status --short; flutter doctor -v; echo "ANDROID_HOME=${ANDROID_HOME:-}"; echo "ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT:-}"; flutter devices'
/Users/toki/jenkins/workspace/nomadcode
a90d15f
 M apps/client/android/gradle.properties
 M apps/client/pubspec.lock
[✓] Flutter (Channel stable, 3.44.0, on macOS 26.0.1 25A362 darwin-arm64, locale ko-KR) [1,554ms]
    • Flutter version 3.44.0 on channel stable at /Users/toki/SDK/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 559ffa3f75 (11 days ago), 2026-05-15 14:13:13 -0700
    • Engine revision 4c525dac5e
    • Dart version 3.12.0
    • DevTools version 2.57.0
    • Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.0s]
    • Android SDK at /Users/toki/Library/Android/sdk
    • Emulator version 35.4.9.0 (build_id 13025442) (CL:N/A)
    • Platform android-36, build-tools 35.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 17.0.11+0-17.0.11b1207.24-11852314)
    • All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.0.1) [2.3s]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 17A400
    • CocoaPods version 1.16.2

[✓] Chrome - develop for the web [7ms]
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (2 available) [11.7s]
    • macOS (desktop) • macos  • darwin-arm64   • macOS 26.0.1 25A362 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 148.0.7778.179

[✓] Network resources [501ms]
    • All expected network resources are available.
• No issues found!
ANDROID_HOME=
ANDROID_SDK_ROOT=
Found 2 connected devices:
  macOS (desktop) • macos  • darwin-arm64   • macOS 26.0.1 25A362 darwin-arm64
  Chrome (web)    • chrome • web-javascript • Google Chrome 148.0.7778.179

Checking for wireless devices...
No wireless devices were found.
Run "flutter emulators" to list and start any available device emulators.

If you expected another device to be detected, please run "flutter doctor" to diagnose potential issues. You may also try increasing the time to wait for connected devices with the "--device-timeout" flag. Visit https://flutter.dev/setup/ for troubleshooting tips.
```

### SMOKE_BUILD-2 중간 검증

```bash
$ ssh toki@toki-labs.com 'export PATH="/opt/homebrew/bin:/usr/local/bin:/Users/toki/SDK/flutter/bin:/opt/homebrew/opt/openjdk@11/bin:/Users/toki/SDK:/Users/toki/Library/Android/sdk/platform-tools:$PATH"; set -euo pipefail; cd /Users/toki/jenkins/workspace/nomadcode/apps/client; flutter pub get; flutter build apk --debug'
Resolving dependencies...
Downloading packages...
  _flutterfire_internals 1.3.59 (1.3.71 available)
  async 2.13.0 (2.13.1 available)
  cupertino_icons 1.0.8 (1.0.9 available)
  firebase_core 3.15.2 (4.9.0 available)
  firebase_core_platform_interface 6.0.2 (7.0.1 available)
  firebase_core_web 2.24.1 (3.7.0 available)
  firebase_messaging 15.2.10 (16.2.2 available)
  firebase_messaging_platform_interface 4.6.10 (4.7.11 available)
  firebase_messaging_web 3.10.10 (4.1.7 available)
  matcher 0.12.19 (0.12.20 available)
  meta 1.18.0 (1.18.2 available)
  protobuf 3.1.0 (6.0.0 available)
  test_api 0.7.11 (0.7.12 available)
  vector_math 2.2.0 (2.3.0 available)
  vm_service 15.0.2 (15.2.0 available)
Got dependencies!
15 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Running Gradle task 'assembleDebug'...
WARNING: Your Android app project: app located at: /Users/toki/jenkins/workspace/nomadcode/apps/client/android/app/build.gradle.kts
applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter.
Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers
WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): nexo_messaging, url_launcher_android
Future versions of Flutter will fail to build if your app uses plugins that apply KGP.

Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin.
If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing
an issue against a plugin: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers#report-incompatible-kotlin-gradle-plugin-usage-to-plugin-authors

If you are a plugin author, please migrate your plugin to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'...                              5.2s
✓ Built build/app/outputs/flutter-apk/app-debug.apk
```

### 최종 검증

```bash
$ cd apps/client
$ flutter test
$ flutter analyze --no-fatal-infos
00:00 +0: loading /config/workspace/nomadcode/apps/client/test/widget_test.dart
00:01 +0: loading /config/workspace/nomadcode/apps/client/test/widget_test.dart
00:02 +0: loading /config/workspace/nomadcode/apps/client/test/widget_test.dart
00:02 +0: ... App renders console dashboard title
00:02 +1: ... App renders console dashboard title
00:02 +2: ... App renders console dashboard title
00:02 +3: ... App renders console dashboard title
00:02 +4: ... App renders console dashboard title
00:02 +5: ... App renders console dashboard title
00:03 +5: ... App renders console dashboard title
00:03 +6: ... WorkspaceHomePage triggers launcher callback on button tap
00:03 +7: ... WorkspaceHomePage triggers launcher callback on button tap
00:03 +7: /config/workspace/nomadcode/apps/client/test/integrations/mattermost_push_host_integration_test.dart: auto-login failure does not block initialize
[MattermostHost] Mattermost auto-login failed: Bad state: credentials missing
00:03 +8: ... WorkspaceHomePage triggers launcher callback on button tap
00:03 +9: ... navigation callbacks are assigned exactly once during initialize
00:03 +10: ... callbacks are assigned exactly once during initialize
00:03 +10: ... notification stream remains consumable through integration
00:03 +11: ... notification stream remains consumable through integration
00:03 +11: ...e/apps/client/test/integrations/proto_socket_lifecycle_test.dart
00:03 +11: ... happy path emits connecting -> connected -> disconnected
00:03 +12: ... happy path emits connecting -> connected -> disconnected
00:03 +12: ... connect failure transitions to failed and records error
00:03 +13: ... connect failure transitions to failed and records error
00:03 +13: ... connect is a no-op when already connecting or connected
00:03 +14: ... connect is a no-op when already connecting or connected
00:03 +14: ... disconnect from disconnected state is a no-op
00:03 +15: ... disconnect from disconnected state is a no-op
00:03 +15: All tests passed!

Analyzing client...
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:26:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:33:5 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:39:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:42:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:49:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:53:5 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:97:5 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:115:9 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:124:9 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:126:9 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:129:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:146:7 • avoid_print
   info • Don't invoke 'print' in production code • lib/src/integrations/mattermost/mattermost_auth_service.dart:148:7 • avoid_print
13 issues found. (ran in 3.6s)
```

```bash
$ ssh toki@toki-labs.com 'export PATH="/opt/homebrew/bin:/usr/local/bin:/Users/toki/SDK/flutter/bin:/opt/homebrew/opt/openjdk@11/bin:/Users/toki/SDK:/Users/toki/Library/Android/sdk/platform-tools:$PATH"; set -euo pipefail; cd /Users/toki/jenkins/workspace/nomadcode/apps/client; flutter pub get; flutter build apk --debug'
Resolving dependencies...
Downloading packages...
  _flutterfire_internals 1.3.59 (1.3.71 available)
  async 2.13.0 (2.13.1 available)
  cupertino_icons 1.0.8 (1.0.9 available)
  firebase_core 3.15.2 (4.9.0 available)
  firebase_core_platform_interface 6.0.2 (7.0.1 available)
  firebase_core_web 2.24.1 (3.7.0 available)
  firebase_messaging 15.2.10 (16.2.2 available)
  firebase_messaging_platform_interface 4.6.10 (4.7.11 available)
  firebase_messaging_web 3.10.10 (4.1.7 available)
  matcher 0.12.19 (0.12.20 available)
  meta 1.18.0 (1.18.2 available)
  protobuf 3.1.0 (6.0.0 available)
  test_api 0.7.11 (0.7.12 available)
  vector_math 2.2.0 (2.3.0 available)
  vm_service 15.0.2 (15.2.0 available)
Got dependencies!
15 packages have newer versions incompatible with dependency constraints.
Try `flutter pub outdated` for more information.
Running Gradle task 'assembleDebug'...
WARNING: Your Android app project: app located at: /Users/toki/jenkins/workspace/nomadcode/apps/client/android/app/build.gradle.kts
applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter.
Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers
WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): nexo_messaging, url_launcher_android
Future versions of Flutter will fail to build if your app uses plugins that apply KGP.

Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin.
If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing
an issue against a plugin: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers#report-incompatible-kotlin-gradle-plugin-usage-to-plugin-authors

If you are a plugin author, please migrate your plugin to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'...                              5.2s
✓ Built build/app/outputs/flutter-apk/app-debug.apk
```


---

> **[IMPLEMENTING AGENT — BEFORE SAVING] Have you filled in every implementation-owned section: completion table, implementation checklist, changes from plan, design decisions, and verification output?**
> If anything is blank, go back and fill it in before saving this file.
> Leave review-agent-only sections unchanged.

## 코드리뷰 결과

### 종합 판정

FAIL

### 차원별 평가

| 차원 | 평가 | 근거 |
|------|------|------|
| Correctness | Pass | Android plugin metadata and `NexoMessagingPlugin` / `NexoFirebaseMessagingService` references line up with the inspected source. |
| Completeness | Fail | The required remote checkout equivalence check is not closed because the remote build ran on a dirty tree, and local source/doc changes are not reconciled in the implementation notes. |
| Test coverage | Pass | No new unit test was planned; local `flutter test` and `flutter analyze --no-fatal-infos` were rerun and completed with only the known `avoid_print` infos. |
| API contract | Pass | The inspected host adapter and plugin package expose the expected `nexo_messaging` / `NexoMessagingPlugin` contract. |
| Code quality | Pass | No new debug prints or dead code were found in the reviewed local diff. |
| Plan deviation | Fail | The remote verification path change was documented, but the dirty remote checkout and unrecorded local modified files were not resolved against the plan scope. |
| Verification trust | Fail | The APK success evidence came from a remote checkout with uncommitted `apps/client/android/gradle.properties` and `apps/client/pubspec.lock` changes that are not present locally. |

### 발견된 문제

- Required: `agent-task/m-mattermost-messaging-android-smoke/01_remote_build/code_review_cloud_G07_0.log:88` shows the remote checkout was dirty before the build (`apps/client/android/gradle.properties`, `apps/client/pubspec.lock`). A review-time remote diff shows Flutter migrator flags and lockfile version bumps that are not present in the local repo, so the `flutter build apk --debug` pass cannot yet be treated as evidence for the current branch/patch. Fix by either adopting the required generated changes locally and rerunning verification, or rerunning the remote build from a clean remote worktree at the target commit/patch; record pre-build status/diff and post-build status in the next review.
- Required: `apps/client/macos/Flutter/GeneratedPluginRegistrant.swift:16` and `apps/client/push-notification-todo.md:35` are local modified files, but `agent-task/m-mattermost-messaging-android-smoke/01_remote_build/code_review_cloud_G07_0.log:64` only records the remote path/PATH deviations. Fix by reconciling the local diff in the follow-up: document each intended local change as part of this task, or explicitly mark unrelated pre-existing changes as out of scope without relying on them for the remote build evidence.

### 다음 단계

FAIL follow-up: archive this review/plan pair, then write the next active `PLAN-cloud-G07.md` and `CODE_REVIEW-cloud-G07.md` focused on remote verification trust recovery.
