appsok/agent-task/m-usb-install/01_adb_bundle/PLAN-cloud-G07.md
toki 9d91b947c6 feat: usb install feature implementation
- Add adb_service.dart with usb install capabilities
- Add adb_service_test.dart for testing
- Update project rules and phase documentation
- Update milestone documents for jenkins-credential and usb-install
- Add agent-task/m-usb-install/ directory with planning documents
2026-06-12 22:05:42 +09:00

11 KiB

Plan - API

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

구현이 끝나면 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 검증을 실행하고, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 최종 판정, log rename, complete.log 작성, task archive 이동은 code-review 전용이다. 사용자만 결정할 수 있는 외부 환경, secret, 범위 충돌로 막히면 리뷰 stub의 사용자 리뷰 요청에 정확한 증거와 재개 조건을 남기고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 request_user_input을 호출하지 않는다.

배경

AdbService는 이제 bundled ADB를 우선 찾고, 없으면 system adb로 fallback한다. 하지만 macOS bundle에는 아직 실제 adb-runtime 리소스가 없어 release 앱에서는 계속 fallback에 의존한다. 이 작업은 pin된 최소 ADB subset을 app bundle 리소스로 포함하고 remote Mac runner에서 실행 가능성을 검증한다.

사용자 리뷰 요청 흐름

구현 중 차단 사유는 active CODE_REVIEW-*-G??.md사용자 리뷰 요청 섹션에 기록한다. 직접 사용자 프롬프트는 금지이며, code-review가 요청 타당성과 USER_REVIEW.md 작성 여부를 판단한다.

Roadmap Targets

  • Milestone: agent-roadmap/phase/usable-mvp/milestones/usb-install.md
  • Task ids:
    • adb-bundle: macOS app bundle에 pin된 최소 ADB subset을 포함한다.
  • Completion mode: check-on-pass

분석 결과

읽은 파일

  • agent-roadmap/current.md
  • agent-roadmap/phase/usable-mvp/PHASE.md
  • agent-roadmap/phase/usable-mvp/milestones/usb-install.md
  • agent-ops/rules/project/domain/device-console/rules.md
  • agent-ops/rules/project/domain/macos-platform/rules.md
  • agent-test/local/rules.md
  • agent-test/local/device-console-smoke.md
  • agent-test/local/macos-platform-smoke.md
  • agent-test/local/macos-remote-build-smoke.md
  • lib/src/services/adb_service.dart
  • test/adb_service_test.dart
  • pubspec.yaml
  • .gitignore
  • macos/Runner.xcodeproj/project.pbxproj
  • macos/Runner/Configs/AppInfo.xcconfig
  • macos/Runner/Configs/Debug.xcconfig
  • macos/Runner/Configs/Release.xcconfig
  • macos/Runner/Configs/Warnings.xcconfig
  • macos/Runner/DebugProfile.entitlements
  • macos/Runner/Release.entitlements
  • macos/Runner/Info.plist
  • macos/Runner/AppDelegate.swift
  • macos/Runner/MainFlutterWindow.swift

테스트 환경 규칙

  • test_env: local
  • env rules: agent-test/local/rules.md present and read. 기본 완료 evidence는 standard remote Mac runner toki@toki-labs.com checkout $HOME/docker/services/code-server/data/volume/workspace/appsok.
  • matched profiles:
    • agent-test/local/device-console-smoke.md: flutter analyze, flutter test; ADB runtime evidence는 remote runner adb 기준.
    • agent-test/local/macos-platform-smoke.md: macOS platform 변경 시 remote flutter build macos.
    • agent-test/local/macos-remote-build-smoke.md: remote checkout 상태, Xcode, signing identity, flutter build macos.
  • 적용 명령:
    • zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && git status --short --branch'
    • zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter pub get'
    • 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'
    • zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter build macos'
    • zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb version'
    • zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && otool -L build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb'
  • <확인 필요> 값 없음. Notary credential은 이 작업 범위가 아니며 가능으로 단정하지 않는다.

테스트 커버리지 공백

  • Bundled ADB path resolution: test/adb_service_test.dart가 bundled path 존재/fallback 정책을 커버한다.
  • macOS resource copy and nested binary runtime: 기존 unit test로 커버되지 않는다. remote flutter build macos, bundled adb version, otool -L evidence가 필요하다.
  • codesign/sandbox USB execution: unit test로 커버되지 않는다. remote runner smoke 결과를 기록해야 한다.

심볼 참조

  • Renamed/removed symbols: none.
  • Call sites for ADB runtime entry points: lib/src/services/adb_service.dart only. Current UI does not instantiate AdbService directly.

분할 판단

  • split decision policy evaluated.
  • Shared task group: agent-task/m-usb-install/
  • 01_adb_bundle: independent first task. macOS bundle resources, Xcode project/build phase, remote build/runtime evidence.
  • 02+01_adb_diagnostics: depends on index 01; predecessor complete.log is missing now, so diagnostics implementation must wait for agent-task/m-usb-install/01_adb_bundle/complete.log or matching archive complete.log.
  • Split is required because bundle packaging/codesign evidence and diagnostics UI/service behavior have different ownership, risk, and verification paths.

범위 결정 근거

  • Include: minimal platform-tools subset under the macOS app bundle, Xcode copy/resource phase, AdbRuntimeConfig default bundle path compatibility, remote Mac verification.
  • Exclude: settings UI diagnostics display, runtime hash/version model beyond smoke evidence, wireless ADB, split APK/APKS/AAB, notarization.
  • Existing AdbService API should not be reworked beyond bundle path compatibility unless remote build reveals a required path fix.

빌드 등급

  • cloud-G07: macOS app bundle resource wiring, nested binary/dylib dependencies, process execution, and remote build evidence are central.

구현 체크리스트

  • macOS app bundle에 Contents/Resources/adb-runtime/가 생성되도록 pin된 ADB subset copy 방식을 구현한다.
  • bundled adb version과 dylib 의존성 확인이 remote Mac runner에서 통과한다.
  • flutter analyze, flutter test, flutter build macos를 remote Mac runner checkout에서 실행한다.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

의존 관계 및 구현 순서

  1. 01_adb_bundle을 먼저 완료한다.
  2. PASS 후 code-review가 complete.log를 만들면 02+01_adb_diagnostics를 시작할 수 있다.

[API-1] Bundle ADB Runtime

문제

  • lib/src/services/adb_service.dart:190-202는 macOS bundle의 Contents/Resources/adb-runtime/adb를 찾지만, macos/Runner.xcodeproj/project.pbxproj:143-149 Resources group에는 adb-runtime이 없다.
  • macos/Runner.xcodeproj/project.pbxproj:213-218 Runner build phases에는 Flutter resources와 framework copy만 있고 ADB runtime copy phase가 없다.
  • macos/Runner.xcodeproj/project.pbxproj:304-320 shell script는 Flutter embed만 수행하므로 nested binary/dylib 준비가 없다.

해결 방법

Before:

macos/Runner.xcodeproj/project.pbxproj:143
33CC11242044D66E0003C045 /* Resources */ = {
  isa = PBXGroup;
  children = (
    33CC10F22044A3C60003C045 /* Assets.xcassets */,
    33CC10F42044A3C60003C045 /* MainMenu.xib */,
    33CC10F72044A3C60003C045 /* Info.plist */,
  );

After:

macos/Runner.xcodeproj/project.pbxproj
Resources children include adb-runtime, and Runner build phases copy it to
$(CONTENTS_FOLDER_PATH)/Resources/adb-runtime before signing/build validation.
  • Add or generate macos/Runner/Resources/adb-runtime/ with the pinned minimum files: adb, required lib64/*.dylib, NOTICE.txt, source.properties.
  • Wire the directory into the Runner target as a copied resource or deterministic shell copy phase. Prefer a folder reference/copy phase that preserves executable bits.
  • Ensure the final path matches AdbRuntimeConfig.effectiveBundledAdbPath: AppSok.app/Contents/Resources/adb-runtime/adb.
  • Preserve sandbox entitlements unless remote evidence proves a specific entitlement change is required; do not disable sandbox just to make ADB work.

수정 파일 및 체크리스트

  • macos/Runner.xcodeproj/project.pbxproj: add resource/copy phase for adb-runtime.
  • macos/Runner/Resources/adb-runtime/**: add pinned runtime subset and license/version metadata.
  • lib/src/services/adb_service.dart: adjust default bundle path only if remote build path differs from the current Contents/Resources/adb-runtime/adb contract.
  • test/adb_service_test.dart: update only if path contract changes.

테스트 작성

  • New Dart unit tests are not required unless AdbRuntimeConfig path behavior changes. Existing test/adb_service_test.dart covers bundle path preference and fallback.
  • Remote smoke evidence is required because actual copied binary/dylib execution is outside unit test scope.

중간 검증

zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter build macos'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && test -x build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb version'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && otool -L build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb'

Expected: build succeeds; adb is executable; version prints platform-tools version; otool -L references bundled or system-resolvable dylibs intentionally.

수정 파일 요약

파일 항목
macos/Runner.xcodeproj/project.pbxproj API-1
macos/Runner/Resources/adb-runtime/** API-1
lib/src/services/adb_service.dart API-1, only if path contract needs adjustment
test/adb_service_test.dart API-1, only if path contract changes

최종 검증

zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && git status --short --branch'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter pub get'
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'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && flutter build macos'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb version'
zsh -lc 'cd "$HOME/docker/services/code-server/data/volume/workspace/appsok" && otool -L build/macos/Build/Products/Release/AppSok.app/Contents/Resources/adb-runtime/adb'

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