From 5af717d432ca9f328812eea729e29adac3c91a28 Mon Sep 17 00:00:00 2001 From: toki Date: Tue, 9 Jun 2026 04:01:12 +0900 Subject: [PATCH] =?UTF-8?q?chore(roadmap):=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=EC=9D=84=20=EB=B0=98=EC=98=81=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 작업 중 누락된 문서, 테마, 테스트 변경을 모두 반영해 원격 동기화할 수 있게 정리한다. --- .../milestones/macos-distribution.md | 11 +- .../usable-mvp/milestones/artifact-browser.md | 49 +++-- .../milestones/jenkins-credential.md | 45 ++--- .../usable-mvp/milestones/product-baseline.md | 2 +- .../usable-mvp/milestones/usb-install.md | 19 +- .../CODE_REVIEW-local-G05.md | 147 +++++++++++++++ .../01_shell_nav_status/PLAN-local-G05.md | 165 +++++++++++++++++ .../CODE_REVIEW-local-G05.md | 148 +++++++++++++++ .../02+01_responsive_ui/PLAN-local-G05.md | 175 ++++++++++++++++++ lib/src/theme/app_theme.dart | 1 + test/widget_test.dart | 13 ++ 11 files changed, 729 insertions(+), 46 deletions(-) create mode 100644 agent-task/m-product-baseline/01_shell_nav_status/CODE_REVIEW-local-G05.md create mode 100644 agent-task/m-product-baseline/01_shell_nav_status/PLAN-local-G05.md create mode 100644 agent-task/m-product-baseline/02+01_responsive_ui/CODE_REVIEW-local-G05.md create mode 100644 agent-task/m-product-baseline/02+01_responsive_ui/PLAN-local-G05.md diff --git a/agent-roadmap/phase/security-distribution/milestones/macos-distribution.md b/agent-roadmap/phase/security-distribution/milestones/macos-distribution.md index 5663cea..df9eedf 100644 --- a/agent-roadmap/phase/security-distribution/milestones/macos-distribution.md +++ b/agent-roadmap/phase/security-distribution/milestones/macos-distribution.md @@ -29,13 +29,13 @@ AppSok을 사내 Mac에서 안정적으로 실행할 수 있도록 signing, nota - [ ] notarization 후 `stapler`로 ticket을 붙인 `.app`, `.zip`, `.dmg`, `.pkg` 중 어떤 산출물을 배포할지 결정한다. - [ ] "아무 맥에서나 설치" 범위를 Apple Silicon only로 볼지, Intel Mac까지 포함하는 universal build로 볼지 결정한다. - [ ] sandbox를 유지할지, ADB 실행 때문에 sandbox 해제가 필요한지 검증한다. - - [ ] ADB binary를 앱에 bundle할지, 사용자 환경의 Android Platform Tools를 사용할지 결정한다. ## 범위 - macOS app bundle metadata - entitlement와 sandbox 검증 - Keychain/network/ADB 실행 smoke test +- bundled ADB runtime의 nested binary/dylib signing과 실행 검증 - Developer ID signing, notarization, staple, MDM 배포 후보 문서화 ## 기능 @@ -46,7 +46,7 @@ AppSok을 사내 Mac에서 안정적으로 실행할 수 있도록 signing, nota - [ ] [network] sandbox 상태에서 Jenkins HTTPS 호출이 가능한지 확인한다. - [ ] [keychain] `flutter_secure_storage` Keychain read/write가 배포 build에서 동작하는지 확인한다. -- [ ] [adb-exec] sandbox 상태에서 `adb devices -l`과 `adb install` 실행 가능 여부를 확인한다. +- [ ] [adb-exec] sandbox 상태에서 bundled `adb devices -l`과 `adb install` 실행 가능 여부를 확인한다. - [ ] [url-scheme] `appsok://` URL scheme이 설치된 앱으로 전달되는지 확인한다. ### Epic: [distribution] 배포 방식 @@ -58,7 +58,7 @@ AppSok을 사내 Mac에서 안정적으로 실행할 수 있도록 signing, nota - [ ] [notary-profile] `notarytool` Keychain profile 존재 여부와 세팅 절차를 비밀값 없이 문서화한다. - [ ] [staple-assess] notarization 후 stapling과 `spctl --assess` 검증 절차를 문서화한다. - [ ] [arch-policy] Apple Silicon only 또는 universal build 배포 정책을 문서화한다. -- [ ] [platform-tools] ADB binary 제공 방식과 업데이트 책임을 정한다. +- [ ] [platform-tools] bundled ADB runtime의 포함 파일, version pinning, 업데이트 책임, NOTICE 보존 방식을 문서화한다. - [ ] [release-checklist] 배포 전 검증 checklist를 작성한다. ## 완료 리뷰 @@ -75,12 +75,15 @@ AppSok을 사내 Mac에서 안정적으로 실행할 수 있도록 signing, nota - Auth Broker 또는 Jenkins plugin 구현 - 중앙 감사 서버 +- 사용자 Mac의 Android Studio 또는 Android Platform Tools 설치를 기본 전제로 삼는 배포 방식 - Windows/Linux desktop target ## 작업 컨텍스트 - 관련 경로: `macos/Runner/`, `macos/Runner.xcodeproj/`, `pubspec.yaml` - 표준선(선택): sandbox는 가능한 유지하고, 불가능한 경우 사유와 대안을 문서화한다. +- 표준선(선택): 내부 ops 도구 기준으로 ADB는 AppSok-managed bundled runtime을 기본 제공하고, 사용자 환경의 `adb`는 override/fallback으로만 둔다. +- 검증 메모: bundled `adb`, 필요한 `lib64/*.dylib`, `NOTICE.txt`, `source.properties`를 포함하고 signing/notarization 전후 실행 여부를 remote Mac runner에서 확인한다. - 선행 작업: 사용 가능한 MVP - 후속 작업: Auth Broker와 Jenkins Plugin 후보 검토 -- 확인 필요: 구현 잠금의 사용자 리뷰 체크리스트가 AppSok 표시명 승인, Developer ID 사용 승인, notary credential profile, 배포 산출물 형식, universal build 필요 여부, 조직 배포 정책, sandbox/ADB 실행 검증, ADB binary 제공 방식을 다룬다. +- 확인 필요: 구현 잠금의 사용자 리뷰 체크리스트가 AppSok 표시명 승인, Developer ID 사용 승인, notary credential profile, 배포 산출물 형식, universal build 필요 여부, 조직 배포 정책, sandbox/ADB 실행 검증을 다룬다. diff --git a/agent-roadmap/phase/usable-mvp/milestones/artifact-browser.md b/agent-roadmap/phase/usable-mvp/milestones/artifact-browser.md index 59be366..f0d8a90 100644 --- a/agent-roadmap/phase/usable-mvp/milestones/artifact-browser.md +++ b/agent-roadmap/phase/usable-mvp/milestones/artifact-browser.md @@ -7,7 +7,7 @@ ## 목표 -사용자가 Jenkins job의 최근 build를 보고, 설치 가능한 Android artifact를 식별해 Mac에 내려받을 수 있게 한다. 다운로드된 artifact는 이후 USB 설치 milestone의 입력이 된다. +사용자가 Jenkins job 목록에서 대상 job을 고르고, 해당 job의 최근 build 중 설치 가능한 `.apk` artifact가 있는 build만 확인해 바로 설치 흐름으로 넘길 수 있게 한다. build 목록은 build number보다 빌드한 사람을 중심으로 요약해 오설치 가능성을 낮춘다. ## 상태 @@ -19,38 +19,50 @@ ## 구현 잠금 -- 상태: 잠금 -- 결정 필요: 아래 체크리스트 - - [ ] 기본 Jenkins job URL 또는 job 선택 방식을 정한다. - - [ ] artifact 필터 기준을 단일 APK로 제한할지, flavor/branch별 패턴을 둘지 결정한다. - - [ ] 다운로드 cache 위치와 보관 기간을 정한다. +- 상태: 해제 +- 결정 필요: 없음 ## 범위 -- Jenkins recent build 조회 -- build number, result, branch, flavor, artifact 표시 -- APK artifact 다운로드와 로컬 cache +- Jenkins job 목록 조회와 대상 job 선택 +- 선택한 job의 recent build 조회 +- `.apk` artifact가 있는 build만 listing +- 빌드한 사람 중심의 build 요약 표시 +- 선택한 build/artifact에서 바로 설치 CTA 노출 +- 설치 시 필요한 `.apk` artifact 임시 다운로드와 설치 흐름 handoff - 권한 없음, artifact 없음, 실패 build 상태 표시 ## 기능 +### Epic: [job-select] Jenkins job 선택 + +로그인 이후 접근 가능한 Jenkins job을 먼저 보여주고 사용자가 설치 대상 job을 고른다. + +- [ ] [job-list] Jenkins job 목록을 조회하고 검색 가능한 리스트로 표시한다. +- [ ] [job-select] 사용자가 job을 선택하면 해당 job의 build 목록으로 진입한다. +- [ ] [job-empty] 접근 가능한 job이 없거나 권한이 없을 때 상태를 구분해 표시한다. + ### Epic: [build-list] build 목록 -Jenkins Remote API에서 최근 build와 artifact metadata를 가져온다. +Jenkins Remote API에서 선택한 job의 최근 build와 `.apk` artifact metadata를 가져온다. -- [ ] [job-query] Jenkins job URL로 build 목록을 조회한다. 검증: mock HTTP 응답 기반 parser test에서 build/result/artifact parsing이 통과한다. +- [ ] [job-query] 선택한 Jenkins job의 build 목록을 조회한다. 검증: mock HTTP 응답 기반 parser test에서 build/requestedBy/result/artifact parsing이 통과한다. +- [ ] [apk-only] `.apk` artifact가 있는 build만 목록에 남긴다. +- [ ] [requested-by] Jenkins cause의 userName/userId를 우선하고 없으면 trigger source 또는 commit author를 fallback으로 사용해 빌드한 사람을 1차 정보로 표시한다. - [ ] [state-badges] success/failure/running/aborted 상태를 구분해 표시한다. -- [ ] [search-filter] build number, branch, flavor, artifact 이름 기준 검색/필터를 제공한다. +- [ ] [summary-row] build number, branch, flavor, result, 시간, artifact 이름은 보조 정보로 요약 표시한다. +- [ ] [search-filter] 빌드한 사람, build number, branch, flavor, artifact 이름 기준 검색/필터를 제공한다. - [ ] [empty-error] 권한 없음, 네트워크 실패, artifact 없음 상태를 구분해 사용자에게 보여준다. -### Epic: [download-cache] 다운로드와 cache +### Epic: [install-ready] 설치 진입 -선택한 APK를 Mac에 내려받고 설치 가능한 파일 경로로 관리한다. +사용자가 build를 선택하면 별도 깊은 탐색 없이 설치 버튼을 바로 노출하고, 설치 요청 시 필요한 파일만 임시로 내려받는다. +- [ ] [install-cta] build/artifact item 선택 시 설치 CTA를 바로 노출한다. - [ ] [download-progress] artifact 다운로드 진행률과 취소 상태를 표시한다. -- [ ] [cache-path] 다운로드 파일을 앱 전용 cache 경로에 저장한다. +- [ ] [temp-download] 다운로드 파일을 앱 임시/staging 경로에 저장하고 설치 완료 또는 취소 후 삭제한다. - [ ] [artifact-verify] 다운로드 완료 후 파일 존재, 확장자, 크기 정보를 확인한다. -- [ ] [handoff] 다운로드된 APK 경로를 USB 설치 흐름으로 넘긴다. +- [ ] [handoff] 다운로드된 APK 경로를 device 선택과 USB 설치 흐름으로 넘긴다. ## 완료 리뷰 @@ -67,11 +79,14 @@ Jenkins Remote API에서 최근 build와 artifact metadata를 가져온다. - split APK/APKS/AAB 다운로드/설치 - Teams deep link로 build를 직접 여는 흐름 - 중앙 다운로드 감사 로그 +- 설치 완료 후 다운로드 파일을 장기 보관하는 cache 정책 ## 작업 컨텍스트 - 관련 경로: `lib/src/features/builds/`, `lib/src/models/jenkins_build.dart`, `lib/src/services/jenkins_client.dart` - 표준선(선택): Jenkins Remote API JSON tree를 사용하고, parsing은 모델/서비스 테스트로 보호한다. +- 표준선(선택): 다운로드 파일은 설치를 위한 임시 staging 산출물이며, 기본 정책은 설치 완료 또는 취소 후 삭제다. +- 표준선(선택): build 목록의 주 정보는 빌드한 사람이며, build number와 branch/flavor/result는 보조 정보다. - 선행 작업: Jenkins 로그인과 credential 수명주기 - 후속 작업: USB 설치와 device 선택 -- 확인 필요: Jenkins job 구조, artifact naming, cache 정책 +- 확인 필요: 없음 diff --git a/agent-roadmap/phase/usable-mvp/milestones/jenkins-credential.md b/agent-roadmap/phase/usable-mvp/milestones/jenkins-credential.md index e8ed12d..9a19f67 100644 --- a/agent-roadmap/phase/usable-mvp/milestones/jenkins-credential.md +++ b/agent-roadmap/phase/usable-mvp/milestones/jenkins-credential.md @@ -7,7 +7,7 @@ ## 목표 -AppSok이 Jenkins에 접근할 수 있는 사용자인지 확인하고, 사용자별 권한으로 Jenkins API를 호출할 credential을 안전하게 저장한다. MVP에서는 수동 API token 입력 또는 WebView 기반 token 자동 발급 중 하나를 선택해 UX와 보안 균형을 맞춘다. +AppSok이 Jenkins에 접근할 수 있는 사용자인지 확인하고, 사용자별 권한으로 Jenkins API를 호출할 credential을 안전하게 저장한다. MVP에서는 사용자가 직접 token을 발급하지 않도록 Jenkins WebView 로그인 후 사용자별 API token을 자동 발급하고 Keychain에 저장한다. ## 상태 @@ -19,38 +19,37 @@ AppSok이 Jenkins에 접근할 수 있는 사용자인지 확인하고, 사용 ## 구현 잠금 -- 상태: 잠금 -- 잠금 해제 조건: 사용자 리뷰에서 아래 항목을 승인하거나 방향을 결정할 때까지 credential 구현 방식을 확정하지 않는다. -- 결정 필요: 사용자 리뷰 체크리스트 - - [ ] MVP 인증 방식을 `수동 API token 입력`으로 시작할지, `Jenkins WebView 로그인 후 token 자동 발급`으로 시작할지 결정한다. - - [ ] Jenkins에서 사용자별 API token 자동 발급 endpoint와 crumb 발급 흐름을 사용할 수 있는지 확인한다. - - [ ] WebView 로그인 방식이 사내 보안 리뷰에서 허용 가능한지 확인한다. +- 상태: 해제 +- 결정 필요: 없음 ## 범위 -- Jenkins base URL과 username/API token 저장 -- credential 저장/삭제/검증 UI -- `/whoAmI` 또는 사용자 API 호출 기반 로그인 상태 확인 +- Jenkins base URL 저장과 WebView 로그인 진입 +- WebView 로그인 세션에서 crumb와 사용자별 API token 자동 발급 +- 자동 발급한 username/API token을 macOS Keychain에 저장 +- 앱 시작 시 저장된 credential을 읽고 `/whoAmI` 또는 사용자 API 호출로 조용히 재검증 +- credential 삭제, 재로그인, token 폐기/권한 없음/네트워크 실패 상태 구분 - macOS Keychain 저장과 로그 redaction ## 기능 -### Epic: [manual-token] 수동 token MVP +### Epic: [web-login] WebView 로그인과 자동 token 발급 -사용자가 직접 만든 Jenkins API token을 AppSok에 저장하고 검증한다. +사용자가 Jenkins 계정으로 로그인하면 AppSok이 같은 세션에서 API token을 자동 발급해 저장한다. -- [ ] [settings-form] Jenkins base URL, username, API token 입력과 저장 UI를 제공한다. -- [ ] [keychain-store] credential을 `TokenStore`를 통해 macOS Keychain에 저장하고 삭제할 수 있다. 검증: mock storage 기반 unit test에서 save/read/clear가 통과한다. -- [ ] [whoami-check] 저장된 credential로 Jenkins 사용자 확인 API를 호출해 로그인 상태를 표시한다. +- [ ] [login-webview] Jenkins 로그인 URL을 WebView로 열고 로그인 완료를 감지한다. +- [ ] [crumb-token] WebView same-origin 요청으로 crumb를 받고 사용자별 API token을 자동 발급한다. +- [ ] [keychain-store] 자동 발급한 username/API token을 `TokenStore`를 통해 macOS Keychain에 저장하고 삭제할 수 있다. 검증: mock storage 기반 unit test에서 save/read/clear가 통과한다. - [ ] [redaction] API token이 화면 오류, debug log, test fixture에 원문으로 남지 않도록 처리한다. -### Epic: [web-login] WebView 자동 token 후보 +### Epic: [session-restore] 로그인 상태 복원 -수동 token UX가 부담스러운 경우를 대비해 Jenkins 로그인 세션에서 token 발급을 자동화할 수 있는 구조를 둔다. +앱을 다시 켤 때 매번 로그인하지 않고 저장된 credential을 검증해 Jenkins 접근 상태를 복원한다. -- [ ] [login-webview] Jenkins 로그인 URL을 WebView로 열고 로그인 완료를 감지하는 화면 흐름을 설계한다. -- [ ] [crumb-token] WebView same-origin 요청으로 crumb와 generate token 호출 후보를 검증한다. -- [ ] [fallback] WebView 자동화가 실패하면 수동 token 입력으로 돌아갈 수 있다. +- [ ] [startup-check] 앱 시작 시 Keychain credential을 읽고 Jenkins 사용자 확인 API로 조용히 검증한다. +- [ ] [auth-state] 검증 성공 시 로그인 화면을 건너뛰고 build 목록으로 진입한다. +- [ ] [reauth] token 폐기, 권한 없음, Jenkins URL 변경, 네트워크 실패를 구분해 재로그인 또는 재시도 흐름으로 안내한다. +- [ ] [logout-clear] 사용자가 저장된 credential을 삭제하고 다시 로그인할 수 있다. ## 완료 리뷰 @@ -67,11 +66,13 @@ AppSok이 Jenkins에 접근할 수 있는 사용자인지 확인하고, 사용 - LDAP 직접 연동 - 공용 Jenkins API token 내장 - Auth Broker 또는 Jenkins plugin 구현 +- 사용자가 Jenkins에서 API token을 직접 발급해 복사하는 흐름을 기본 UX로 삼는 방식 ## 작업 컨텍스트 - 관련 경로: `lib/src/features/settings/`, `lib/src/services/token_store.dart`, `lib/src/services/jenkins_client.dart`, `macos/Runner/*.entitlements` -- 표준선(선택): 사용자별 Jenkins 권한과 Keychain 저장을 기본 전제로 한다. +- 표준선(선택): 사용자별 Jenkins 권한, WebView 로그인 기반 자동 token 발급, Keychain 저장을 기본 전제로 한다. +- 표준선(선택): API token은 OAuth refresh token처럼 갱신하는 토큰이 아니라 저장 후 재검증하는 credential로 다룬다. - 선행 작업: 제품 골격 안정화 - 후속 작업: Artifact 탐색과 다운로드 -- 확인 필요: 구현 잠금의 사용자 리뷰 체크리스트가 MVP 인증 방식, Jenkins token 자동 발급 가능 여부, WebView 로그인 허용 여부를 다룬다. +- 확인 필요: 없음 diff --git a/agent-roadmap/phase/usable-mvp/milestones/product-baseline.md b/agent-roadmap/phase/usable-mvp/milestones/product-baseline.md index bc53752..7d54b42 100644 --- a/agent-roadmap/phase/usable-mvp/milestones/product-baseline.md +++ b/agent-roadmap/phase/usable-mvp/milestones/product-baseline.md @@ -37,7 +37,7 @@ AppSok의 Flutter macOS scaffold를 실제 기능 구현이 가능한 기준선 - [ ] [nav-shell] 좌측 navigation과 상단 Jenkins/ADB 상태 영역을 실제 상태 연결 전에도 안정적으로 표시한다. 검증: `flutter test`에서 app shell 렌더링과 navigation 전환이 통과한다. - [ ] [responsive-ui] 기본 테스트 viewport에서 텍스트/버튼 overflow가 없도록 card, badge, toolbar 크기를 안정화한다. 검증: `flutter test`가 overflow exception 없이 통과한다. -- [ ] [theme] AppSok 이름과 업무 앱 성격에 맞는 Material theme 기준선을 유지한다. +- [x] [theme] AppSok 이름과 업무 앱 성격에 맞는 Material theme 기준선을 유지한다. ### Epic: [ops] 작업 운영 기준선 diff --git a/agent-roadmap/phase/usable-mvp/milestones/usb-install.md b/agent-roadmap/phase/usable-mvp/milestones/usb-install.md index 7b99c79..1f41b58 100644 --- a/agent-roadmap/phase/usable-mvp/milestones/usb-install.md +++ b/agent-roadmap/phase/usable-mvp/milestones/usb-install.md @@ -24,6 +24,9 @@ USB로 연결된 Android device를 표시하고, 선택한 단일 APK를 `adb in ## 범위 +- AppSok에 포함된 pin된 ADB runtime을 기본 실행 경로로 사용 +- 사용자 지정 또는 system `adb`는 override/fallback으로만 허용 +- AppSok 전용 ADB server port를 기본값으로 사용하고 공유 server fallback 제공 - `adb devices -l` 기반 device 목록 - unauthorized/offline/device 상태 표시 - 설치 대상 device 선택 @@ -32,11 +35,19 @@ USB로 연결된 Android device를 표시하고, 선택한 단일 APK를 `adb in ## 기능 +### Epic: [adb-runtime] ADB 실행 환경 + +사용자 Mac의 Android Studio, SDK 설치, shell `PATH`에 흔들리지 않는 AppSok-managed ADB runtime을 제공한다. + +- [ ] [adb-path] bundled `adb`를 기본 실행 경로로 선택하고, 사용자가 지정한 custom/system `adb`는 명시적 override 또는 fallback으로만 사용한다. +- [ ] [adb-bundle] macOS app bundle에 pin된 최소 ADB subset(`adb`, 필요한 `lib64/*.dylib`, `NOTICE.txt`, `source.properties`)을 포함한다. 검증: remote Mac runner에서 bundled `adb version`과 dylib 의존성 확인이 통과한다. +- [ ] [adb-server] AppSok 전용 ADB server port를 기본으로 사용하고, Android Studio/CLI와 같은 기존 server를 써야 하는 경우 공유 `5037` 모드로 전환할 수 있다. +- [ ] [adb-diagnostics] ADB 실행 경로, bundled version, runtime hash, server port, fallback 여부를 진단 정보로 표시한다. + ### Epic: [device-list] device 탐색 연결된 Android device를 사용자가 이해할 수 있는 형태로 보여준다. -- [ ] [adb-path] 설정된 adb path 또는 PATH의 `adb` 실행 가능 여부를 확인한다. - [ ] [parse-devices] `adb devices -l` 결과를 serial/state/model/product로 parsing한다. 검증: `device`, `unauthorized`, `offline` fixture test가 통과한다. - [ ] [device-state] USB debugging 승인 필요, offline, ready 상태를 UI에서 구분한다. - [ ] [refresh] 사용자가 device 목록을 새로고침할 수 있다. @@ -62,14 +73,18 @@ USB로 연결된 Android device를 표시하고, 선택한 단일 APK를 `adb in ## 범위 제외 +- 전체 Android SDK 또는 Android Studio 설치 자동화 +- `fastboot`, `sqlite3`, `mke2fs` 등 설치 흐름에 필요 없는 platform-tools 구성요소 - `adb install-multiple` - AAB를 APK로 변환하는 `bundletool` - 무선 ADB pairing ## 작업 컨텍스트 -- 관련 경로: `lib/src/features/devices/`, `lib/src/models/adb_device.dart`, `lib/src/services/adb_service.dart` +- 관련 경로: `lib/src/features/devices/`, `lib/src/models/adb_device.dart`, `lib/src/services/adb_service.dart`, `macos/Runner/` +- 표준선(선택): 내부 ops 도구이므로 AppSok-managed bundled ADB를 기본값으로 삼고, shell `PATH` 의존은 fallback으로만 둔다. - 표준선(선택): 화면 코드에서 `Process`를 직접 호출하지 않고 `AdbService`를 통해 실행한다. +- 검증 메모: macOS bundle 안의 nested binary/dylib codesign과 sandbox 상태의 USB/ADB 실행은 remote Mac runner에서 smoke 검증한다. - 선행 작업: Artifact 탐색과 다운로드 - 후속 작업: ADB 콘솔과 logcat - 확인 필요: 없음 diff --git a/agent-task/m-product-baseline/01_shell_nav_status/CODE_REVIEW-local-G05.md b/agent-task/m-product-baseline/01_shell_nav_status/CODE_REVIEW-local-G05.md new file mode 100644 index 0000000..6ec8147 --- /dev/null +++ b/agent-task/m-product-baseline/01_shell_nav_status/CODE_REVIEW-local-G05.md @@ -0,0 +1,147 @@ + + +# Code Review Reference - SHELL_NAV + +> **[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. +> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves. +> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-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-06-09 +task=m-product-baseline/01_shell_nav_status, plan=0, tag=SHELL_NAV + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/usable-mvp/milestones/product-baseline.md` +- Task ids: + - `nav-shell`: 좌측 navigation과 상단 Jenkins/ADB 상태 영역을 실제 상태 연결 전에도 안정적으로 표시한다. +- Completion mode: check-on-pass + +## 이 파일을 읽는 리뷰 에이전트에게 + +> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다. + +각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요. +리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다. + +1. 판정을 append한다. +2. `CODE_REVIEW-local-G05.md` -> `code_review_local_G05_N.log`, `PLAN-local-G05.md` -> `plan_local_G05_M.log`로 아카이브한다. +3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-product-baseline/01_shell_nav_status/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다. +4. PASS이고 task group이 `m-`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다. +5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다. + +--- + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [SHELL_NAV-1] Shell navigation/status baseline | [ ] | + +## 구현 체크리스트 + +- [ ] 좌측 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의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## 코드리뷰 전용 체크리스트 + +> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다. +> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다. + +- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다. +- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다. +- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G05_N.log`로 아카이브한다. +- [ ] active `PLAN-*-G??.md`를 `plan_local_G05_M.log`로 아카이브한다. +- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다. +- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다. +- [ ] PASS이면 active task 디렉터리 `agent-task/m-product-baseline/01_shell_nav_status/`를 `agent-task/archive/YYYY/MM/m-product-baseline/01_shell_nav_status/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다. +- [ ] PASS이고 task group이 `m-`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다. +- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-product-baseline/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다. +- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-local-G05.md`와 `CODE_REVIEW-local-G05.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`를 남기지 않는다. +- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다. + +## 계획 대비 변경 사항 + +_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._ + +## 주요 설계 결정 + +_구현 에이전트가 주요 설계 결정 사항을 기록한다._ + +## 사용자 리뷰 요청 + +_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._ + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- shell에서 Jenkins API, Keychain, ADB Process를 직접 호출하지 않았는지 확인한다. +- navigation destination 4개가 모두 전환 테스트로 보호되는지 확인한다. +- `Jenkins 대기`, `ADB 대기` placeholder가 실제 상태 연결 전에도 안정적으로 표시되는지 확인한다. + +## 검증 결과 + +_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._ + +필수 규칙: +- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다. +- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다. +- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다. +- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다. +- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다. + +### SHELL_NAV-1 중간 검증 +```bash +$ flutter test +(output) +``` + +### 최종 검증 +```bash +$ dart format lib/src/features/app_shell.dart test/widget_test.dart +(output) + +$ flutter analyze +(output) + +$ flutter test +(output) +``` + +--- + +> **[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. + +## 섹션 소유권 + +| Section | Owner | Note | +|---------|-------|------| +| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these. | +| Roadmap Targets | Fixed at stub creation from plan | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS. | +| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` to `[x]` only. | +| 구현 체크리스트 | Implementing agent | Check `[ ]` to `[x]` only; final checkbox is mandatory before saving. | +| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section. | +| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content. | +| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed. | +| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan. | +| 검증 결과 | Implementing agent | Fill command output only; command changes require a `계획 대비 변경 사항` entry. | +| 코드리뷰 결과 | Review agent appends | Not included until review. | diff --git a/agent-task/m-product-baseline/01_shell_nav_status/PLAN-local-G05.md b/agent-task/m-product-baseline/01_shell_nav_status/PLAN-local-G05.md new file mode 100644 index 0000000..635cde6 --- /dev/null +++ b/agent-task/m-product-baseline/01_shell_nav_status/PLAN-local-G05.md @@ -0,0 +1,165 @@ + + +# 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/agent-task/m-product-baseline/02+01_responsive_ui/CODE_REVIEW-local-G05.md b/agent-task/m-product-baseline/02+01_responsive_ui/CODE_REVIEW-local-G05.md new file mode 100644 index 0000000..24b772d --- /dev/null +++ b/agent-task/m-product-baseline/02+01_responsive_ui/CODE_REVIEW-local-G05.md @@ -0,0 +1,148 @@ + + +# Code Review Reference - RESPONSIVE_UI + +> **[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. +> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. Evidence gaps that a follow-up agent can close by rerunning commands or collecting artifacts are normal follow-up issues, not user-review blockers by themselves. +> Do not ask the user directly, present choices in chat, or call `request_user_input` during implementation; record the needed decision in `사용자 리뷰 요청` and stop for code-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-06-09 +task=m-product-baseline/02+01_responsive_ui, plan=0, tag=RESPONSIVE_UI + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/usable-mvp/milestones/product-baseline.md` +- Task ids: + - `responsive-ui`: 기본 테스트 viewport에서 텍스트/버튼 overflow가 없도록 card, badge, toolbar 크기를 안정화한다. +- Completion mode: check-on-pass + +## 이 파일을 읽는 리뷰 에이전트에게 + +> **[REVIEW AGENT ONLY]** 아래 종결 절차는 코드리뷰 에이전트 전용이다. 구현 에이전트는 이 섹션을 실행하지 않는다. + +각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요. +리뷰 완료는 아래 순서까지 끝난 상태를 의미합니다. + +1. 판정을 append한다. +2. `CODE_REVIEW-local-G05.md` -> `code_review_local_G05_N.log`, `PLAN-local-G05.md` -> `plan_local_G05_M.log`로 아카이브한다. +3. PASS이면 `complete.log` 작성 후 active task 디렉터리를 `agent-task/archive/YYYY/MM/m-product-baseline/02+01_responsive_ui/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. `USER_REVIEW.md`가 사용자 결정으로 완료/PASS 해소되면 code-review가 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log` 작성 후 archive 이동한다. +4. PASS이고 task group이 `m-`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다. +5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다. + +--- + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [RESPONSIVE_UI-1] Overflow-safe shell and placeholder screens | [ ] | + +## 구현 체크리스트 + +- [ ] `agent-task/m-product-baseline/01_shell_nav_status/complete.log`가 존재하는지 확인하고 없으면 이 plan 구현을 시작하지 않는다. +- [ ] top bar, toolbar, card, badge, button layout이 기본 테스트 viewport에서 overflow를 내지 않도록 `AppSokShell`과 placeholder page layout을 안정화한다. 검증: `flutter test`가 overflow exception 없이 통과한다. +- [ ] `test/widget_test.dart`에 작은 viewport smoke test를 추가하고 build/device/console/settings 화면을 순회해 overflow exception이 없음을 검증한다. +- [ ] `dart format 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 test/widget_test.dart`를 실행한다. +- [ ] `flutter analyze`와 `flutter test`를 실행한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## 코드리뷰 전용 체크리스트 + +> **[REVIEW AGENT ONLY]** 이 체크리스트는 코드리뷰 에이전트만 사용한다. +> 구현 에이전트는 이 섹션을 수정하거나 체크하지 않는다. + +- [ ] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다. +- [ ] 판정과 `차원별 평가`, Required/Suggested/Nit 분류가 서로 일치한다. +- [ ] active `CODE_REVIEW-*-G??.md`를 `code_review_local_G05_N.log`로 아카이브한다. +- [ ] active `PLAN-*-G??.md`를 `plan_local_G05_M.log`로 아카이브한다. +- [ ] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하고 `agent-roadmap/current.md`를 ignore하는지 확인한다. +- [ ] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다. +- [ ] PASS이면 active task 디렉터리 `agent-task/m-product-baseline/02+01_responsive_ui/`를 `agent-task/archive/YYYY/MM/m-product-baseline/02+01_responsive_ui/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다. +- [ ] PASS이고 task group이 `m-`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다. +- [ ] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-product-baseline/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다. +- [ ] WARN/FAIL이고 user-review gate가 트리거되지 않았으면 다음 active `PLAN-local-G05.md`와 `CODE_REVIEW-local-G05.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`를 남기지 않는다. +- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다. + +## 계획 대비 변경 사항 + +_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._ + +## 주요 설계 결정 + +_구현 에이전트가 주요 설계 결정 사항을 기록한다._ + +## 사용자 리뷰 요청 + +_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._ + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- `01_shell_nav_status` 완료 이후 구현되었는지 확인한다. +- 작은 viewport test가 실제로 build/device/console/settings 화면을 모두 순회하는지 확인한다. +- responsive 조정이 실제 feature 구현 범위로 번지지 않았는지 확인한다. + +## 검증 결과 + +_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._ + +필수 규칙: +- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다. +- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다. +- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다. +- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다. +- mobile/UI hang, timeout, 또는 2분 무진행은 blind retry를 중단하고 focused rerun 명령과 screenshot/window/UI-tree evidence path를 남기며, 불가능하면 정확한 사유를 남긴다. + +### RESPONSIVE_UI-1 중간 검증 +```bash +$ flutter test +(output) +``` + +### 최종 검증 +```bash +$ dart format 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 test/widget_test.dart +(output) + +$ flutter analyze +(output) + +$ flutter test +(output) +``` + +--- + +> **[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. + +## 섹션 소유권 + +| Section | Owner | Note | +|---------|-------|------| +| Header comment, 개요, 리뷰 에이전트 지시 | Fixed at stub creation | Implementing agent must not modify or execute these. | +| Roadmap Targets | Fixed at stub creation from plan | Implementing agent must not modify; code-review copies it into `complete.log` as `Roadmap Completion` only on PASS. | +| 구현 항목별 완료 여부 | Implementing agent | Check `[ ]` to `[x]` only. | +| 구현 체크리스트 | Implementing agent | Check `[ ]` to `[x]` only; final checkbox is mandatory before saving. | +| 코드리뷰 전용 체크리스트 | Review agent only | Implementing agent must not modify or check this section. | +| 계획 대비 변경 사항, 주요 설계 결정 | Implementing agent | Replace placeholder text with actual content. | +| 사용자 리뷰 요청 | Implementing agent | Keep `상태: 없음` unless user input is required to proceed. | +| 리뷰어를 위한 체크포인트 | Fixed at stub creation | Pre-filled from plan. | +| 검증 결과 | Implementing agent | Fill command output only; command changes require a `계획 대비 변경 사항` entry. | +| 코드리뷰 결과 | Review agent appends | Not included until review. | diff --git a/agent-task/m-product-baseline/02+01_responsive_ui/PLAN-local-G05.md b/agent-task/m-product-baseline/02+01_responsive_ui/PLAN-local-G05.md new file mode 100644 index 0000000..069eca7 --- /dev/null +++ b/agent-task/m-product-baseline/02+01_responsive_ui/PLAN-local-G05.md @@ -0,0 +1,175 @@ + + +# Plan - RESPONSIVE_UI + +## 이 파일을 읽는 구현 에이전트에게 + +`CODE_REVIEW-local-G05.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 필수 마지막 단계다. 구현 후 검증을 실행하고 실제 변경 내용, 검증 출력, 계획 대비 변경 사항을 기록한 뒤 active 파일을 그대로 둔 채 리뷰 준비를 보고한다. 사용자만 결정할 수 있는 차단, 사용자 소유 외부 환경, 범위 충돌이 생기면 리뷰 stub의 `사용자 리뷰 요청` 섹션에 근거를 남기고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 닫을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다. + +## 배경 + +현재 placeholder 화면들은 desktop 기본 폭에서는 읽기 쉽지만 toolbar와 row가 고정 `Row` 중심이라 좁은 테스트 viewport에서 overflow 가능성이 있다. 첫 Epic의 responsive task는 실제 Jenkins/ADB 연결 전에 텍스트, 버튼, badge, toolbar가 layout을 흔들지 않는 기준선을 만드는 일이다. + +## 사용자 리뷰 요청 흐름 + +구현 중 차단은 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: + - `responsive-ui`: 기본 테스트 viewport에서 텍스트/버튼 overflow가 없도록 card, badge, toolbar 크기를 안정화한다. +- 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 기준이다. +- `<확인 필요>` 값은 없다. + +### 테스트 커버리지 공백 + +- overflow regression: 기존 `test/widget_test.dart`에는 작은 viewport를 설정하고 shell/toolbar/page를 렌더링하는 테스트가 없다. +- Builds toolbar: `lib/src/features/builds/builds_page.dart:17`-`54`가 고정 `Row`라 좁은 폭에서 입력 2개와 로그인 버튼이 겹칠 수 있다. +- Console toolbar: `lib/src/features/console/console_page.dart:16`-`48`가 fixed `Row`라 필터 입력, segmented control, icon button 조합이 좁은 폭에서 overflow할 수 있다. +- Settings form: `lib/src/features/settings/settings_page.dart:24`-`51`, `74`-`89`가 fixed `Row`라 좁은 폭에서 입력과 버튼이 overflow할 수 있다. + +### 심볼 참조 + +- none. 이름 변경이나 제거 계획은 없다. + +### 분할 판단 + +- split decision policy를 먼저 평가했다. +- 공유 task group은 `agent-task/m-product-baseline/`. +- `01_shell_nav_status`: 선행 shell 구조와 navigation/status 테스트를 고정한다. +- `02+01_responsive_ui`: 이 plan이며, directory 이름 기준으로 predecessor `01_shell_nav_status`의 `complete.log`가 필요하다. +- 현재 확인 시 predecessor `agent-task/m-product-baseline/01_shell_nav_status/complete.log`는 아직 없다. 구현 시작 전 runtime 또는 구현 에이전트는 해당 predecessor completion을 확인해야 한다. + +### 범위 결정 근거 + +- 실제 Jenkins job/token/artifact 동작 구현은 `jenkins-credential`, `artifact-browser` Milestone 소관이므로 제외한다. +- 실제 ADB process/device install/logcat 구현은 `usb-install`, `logcat-console` Milestone 소관이므로 제외한다. +- visual redesign이나 feature completion이 아니라 overflow 없는 placeholder shell 기준선만 다룬다. + +### 빌드 등급 + +- `local-G05`: 여러 placeholder 화면과 widget test를 건드리지만 app-shell UI 안정화로 범위가 제한되고 검증이 `flutter analyze/test`로 결정적이다. + +## 구현 체크리스트 + +- [ ] `agent-task/m-product-baseline/01_shell_nav_status/complete.log`가 존재하는지 확인하고 없으면 이 plan 구현을 시작하지 않는다. +- [ ] top bar, toolbar, card, badge, button layout이 기본 테스트 viewport에서 overflow를 내지 않도록 `AppSokShell`과 placeholder page layout을 안정화한다. 검증: `flutter test`가 overflow exception 없이 통과한다. +- [ ] `test/widget_test.dart`에 작은 viewport smoke test를 추가하고 build/device/console/settings 화면을 순회해 overflow exception이 없음을 검증한다. +- [ ] `dart format 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 test/widget_test.dart`를 실행한다. +- [ ] `flutter analyze`와 `flutter test`를 실행한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +### [RESPONSIVE_UI-1] Overflow-safe shell and placeholder screens + +#### 문제 + +- `lib/src/features/app_shell.dart:151`-`162`의 top bar는 fixed `Row`와 status pill 2개를 사용해 좁은 폭에서 title/status가 밀릴 수 있다. +- `lib/src/features/builds/builds_page.dart:17`-`54`의 toolbar는 `TextField` 2개와 `FilledButton`을 fixed `Row`에 둔다. +- `lib/src/features/console/console_page.dart:16`-`48`의 toolbar는 필터 입력, segmented control, icon button 2개를 fixed `Row`에 둔다. +- `lib/src/features/settings/settings_page.dart:24`-`51`, `74`-`89`의 form row는 입력과 버튼이 좁은 폭에서 줄바꿈되지 않는다. +- `test/widget_test.dart:19`-`35`는 overflow를 잡는 viewport test가 없다. + +#### 해결 방법 + +LayoutBuilder, Wrap, ConstrainedBox, Flexible을 사용해 toolbar와 form row가 좁은 폭에서 자연스럽게 줄바꿈되도록 한다. 버튼은 icon+label이 필요한 곳만 유지하고, compact 영역에서는 icon button 또는 fixed min width로 layout shift를 줄인다. + +Before: + +```dart +// lib/src/features/builds/builds_page.dart:17 +Row( + children: [ + Expanded( + flex: 3, + child: TextField( + decoration: InputDecoration( + labelText: 'Jenkins job URL', +``` + +#### 수정 파일 및 체크리스트 + +- [ ] `lib/src/features/app_shell.dart`: top bar title/status pill 영역을 overflow-safe하게 만든다. +- [ ] `lib/src/features/builds/builds_page.dart`: toolbar와 build row action 버튼이 좁은 폭에서 overflow 없이 배치되도록 조정한다. +- [ ] `lib/src/features/devices/devices_page.dart`: filter/action row와 tile chip/button row가 안정적인 크기를 유지하는지 확인하고 필요 시 보강한다. +- [ ] `lib/src/features/console/console_page.dart`: filter/level/action toolbar가 줄바꿈 또는 compact 배치되도록 조정한다. +- [ ] `lib/src/features/settings/settings_page.dart`: form row를 좁은 폭에서 세로 배치 또는 wrap으로 전환한다. +- [ ] `test/widget_test.dart`: 작은 viewport smoke test를 추가한다. + +#### 테스트 작성 + +- 작성한다. +- 경로: `test/widget_test.dart` +- 테스트명 후보: `renders shell pages without overflow at compact viewport` +- assertion 목표: `tester.view.physicalSize`와 `devicePixelRatio`를 설정한 뒤 빌드, 디바이스, 콘솔, 설정 화면을 순회하고 `tester.takeException()`이 null임을 확인한다. + +#### 중간 검증 + +```bash +flutter test +``` + +기대 결과: compact viewport smoke를 포함한 모든 widget test가 통과한다. + +## 의존 관계 및 구현 순서 + +- 이 plan은 directory 이름 `02+01_responsive_ui` 기준으로 `01_shell_nav_status`에 의존한다. +- 구현 시작 전 `agent-task/m-product-baseline/01_shell_nav_status/complete.log` 또는 archive의 같은 predecessor complete log를 확인한다. + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `lib/src/features/app_shell.dart` | RESPONSIVE_UI-1 | +| `lib/src/features/builds/builds_page.dart` | RESPONSIVE_UI-1 | +| `lib/src/features/devices/devices_page.dart` | RESPONSIVE_UI-1 | +| `lib/src/features/console/console_page.dart` | RESPONSIVE_UI-1 | +| `lib/src/features/settings/settings_page.dart` | RESPONSIVE_UI-1 | +| `test/widget_test.dart` | RESPONSIVE_UI-1 | + +## 최종 검증 + +```bash +dart format 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 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/lib/src/theme/app_theme.dart b/lib/src/theme/app_theme.dart index 706fbf7..b21f7f2 100644 --- a/lib/src/theme/app_theme.dart +++ b/lib/src/theme/app_theme.dart @@ -29,6 +29,7 @@ class AppTheme { useMaterial3: true, colorScheme: colorScheme, scaffoldBackgroundColor: colorScheme.surface, + splashFactory: InkRipple.splashFactory, fontFamily: 'Apple SD Gothic Neo', textTheme: const TextTheme( headlineSmall: TextStyle(fontWeight: FontWeight.w800), diff --git a/test/widget_test.dart b/test/widget_test.dart index 2030141..4101eb3 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,8 +1,21 @@ +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:appsok/src/app.dart'; +import 'package:appsok/src/theme/app_theme.dart'; void main() { + test('keeps the AppSok work app theme baseline', () { + final theme = AppTheme.light(); + final colorScheme = theme.colorScheme; + + expect(theme.useMaterial3, isTrue); + expect(colorScheme.primary, const Color(0xFF0B6E69)); + expect(colorScheme.secondary, const Color(0xFFD66B3D)); + expect(colorScheme.tertiary, const Color(0xFF6655A8)); + expect(theme.scaffoldBackgroundColor, const Color(0xFFFAFBF7)); + }); + testWidgets('renders the app shell', (WidgetTester tester) async { await tester.pumpWidget(const AppSokApp());