From 1f1527d7c6b8f115ba12c951c9919d779f071b23 Mon Sep 17 00:00:00 2001 From: toki Date: Sun, 31 May 2026 21:11:10 +0900 Subject: [PATCH] feat: Flutter Operator Console milestone completion and migration to archive - Move flutter-operator-console milestone to archive (completed) - Add AltWorkbenchShell for workbench pattern migration - Update router and dashboard screen for workbench integration - Update agent-roadmap and phase documentation - Headless workflow validation complete (02+01_headless_validation) - Update client domain rules and README --- README.md | 5 +- .../rules/project/domain/client/rules.md | 5 + .../milestones/flutter-operator-console.md | 10 +- agent-roadmap/current.md | 4 +- agent-roadmap/phase/operator-surface/PHASE.md | 8 +- .../operator-headless-workflow-validation.md | 9 +- .../code_review_cloud_G07_0.log | 208 ++++++++++ .../01_ux_scope_gate/complete.log | 43 ++ .../01_ux_scope_gate/plan_cloud_G07_0.log | 181 +++++++++ .../code_review_cloud_G07_0.log | 246 ++++++++++++ .../02+01_headless_validation/complete.log | 44 +++ .../plan_cloud_G07_0.log | 190 +++++++++ apps/client/README.md | 6 + .../lib/src/app/alt_workbench_shell.dart | 368 ++++++++++++++++++ apps/client/lib/src/app/router.dart | 8 +- .../presentation/dashboard_screen.dart | 15 +- apps/client/pubspec.lock | 7 + apps/client/pubspec.yaml | 4 + apps/client/test/app/bootstrap_test.dart | 110 +++--- apps/client/test/widget_test.dart | 55 ++- 20 files changed, 1445 insertions(+), 81 deletions(-) rename agent-roadmap/{ => archive}/phase/operator-surface/milestones/flutter-operator-console.md (96%) create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/code_review_cloud_G07_0.log create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/plan_cloud_G07_0.log create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/code_review_cloud_G07_0.log create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/complete.log create mode 100644 agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/plan_cloud_G07_0.log create mode 100644 apps/client/lib/src/app/alt_workbench_shell.dart diff --git a/README.md b/README.md index 0624a79..d3f5b90 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Go 서비스와 도구는 루트 `go.work`로 묶고, Flutter가 web/mobile/desk - `services/api`는 proto-socket WebSocket endpoint scaffold를 제공한다. - `services/worker`는 데이터 수집, 정규화, 백테스트, scheduled job을 위한 worker surface다. -- `apps/client`는 Riverpod과 `go_router`를 사용하는 Flutter client shell이다. +- `apps/client`는 Riverpod과 `go_router`를 사용하는 Flutter client shell이다. 현재 NomadCode와 같은 top titlebar, 우측 activity rail, 우측 Agent dock 패턴의 workbench scaffold를 포함하며 Agent dock은 공통 `agent_shell` package를 사용한다. - `packages/contracts`에는 `alt.v1` protobuf 계약 초안이 있다. - `packages/domain`에는 market/backtest vocabulary와 value object skeleton이 있다. - PostgreSQL 17과 Redis 7 local stack은 `deployments/local/docker-compose.yml`에 있다. @@ -67,7 +67,7 @@ bin/build | `services/api/` | 클라이언트-facing proto-socket API endpoint. | | `services/worker/` | import, normalization, backtest, scheduled job worker surface. | | `apps/cli/` | 로컬/운영자 작업용 Go CLI. | -| `apps/client/` | Flutter client for web/mobile/desktop. | +| `apps/client/` | Flutter client for web/mobile/desktop. Workbench shell, 우측 Agent dock, Riverpod/go_router app boundary를 포함한다. | | `packages/contracts/` | ALT protobuf contracts and compatibility notes. | | `packages/domain/` | market/backtest shared Go domain model. | | `deployments/local/` | local PostgreSQL and Redis development environment. | @@ -93,6 +93,7 @@ AI agent는 작업 전에 루트 지침과 관련 domain rule을 먼저 확인 - `services/api`는 socket/session boundary를 담당한다. - `services/worker`는 오래 걸리거나 비동기적인 데이터/백테스트 작업을 담당한다. - `apps/client`는 Flutter feature-first 구조를 사용한다. +- `apps/client`의 workbench shell은 UI skeleton 수준이며, 실제 quant 운영 기능은 API/worker/domain headless 경계가 안정화된 뒤 중앙 section에 mount한다. ## 개발 흐름 diff --git a/agent-ops/rules/project/domain/client/rules.md b/agent-ops/rules/project/domain/client/rules.md index 5104c61..1b8d270 100644 --- a/agent-ops/rules/project/domain/client/rules.md +++ b/agent-ops/rules/project/domain/client/rules.md @@ -32,6 +32,7 @@ ALT의 Flutter client surface를 담당한다. web/mobile/desktop targets, appli ## 주요 구성 요소 - `AltClientApp` - Material app shell using Riverpod +- `AltWorkbenchShell` - top titlebar, right-side activity rail, center content switching, and right Agent dock scaffold - `appRouterProvider` - `go_router` configuration - `DashboardScreen` - initial responsive dashboard surface - `altParserMap` - generated ALT protobuf message parser registration for Dart clients @@ -46,6 +47,8 @@ ALT의 Flutter client surface를 담당한다. web/mobile/desktop targets, appli - Keep app-level shell and router under `lib/src/app`. - Put user-facing screens under the `lib/src/features/feature-name/presentation` pattern. - Put socket and other external adapters under `lib/src/integrations`. +- Keep the workbench shell as product skeleton and composition boundary. Real quant operation surfaces are mounted after API/worker/domain headless paths are stable. +- Use sibling `agent_shell` for the common chat/agent UI only; keep ALT-specific market/backtest/portfolio logic in ALT client features or backend domains. - Treat files under `lib/src/generated` as generated outputs; update them through codegen. - Use Material 3 components and responsive navigation patterns. - Test user-visible app shell behavior through Flutter tests. @@ -58,6 +61,7 @@ ALT의 Flutter client surface를 담당한다. web/mobile/desktop targets, appli - **api**: client connects to API through integration adapters; server lifecycle and server-side socket parsing stay in `services/api`. - **contracts**: client consumes generated/mapped contracts and owns Dart parser helpers; protobuf source stays in `packages/contracts`. +- **agent-shell**: common agent shell widget/message model only. ALT-specific quant workflow logic stays in ALT-owned client/core domains. - **operations**: `bin/test`, `bin/lint`, and `bin/build` run client checks from the workspace root. - **worker**: client never connects to worker directly; worker state reaches client only through API contracts. @@ -67,5 +71,6 @@ ALT의 Flutter client surface를 담당한다. web/mobile/desktop targets, appli - Do not hand-edit platform generated files unless the Flutter platform integration explicitly requires it. - Do not hand-edit generated protobuf Dart outputs. - Do not hard-code production endpoint assumptions in presentation widgets. +- Do not put ALT-specific quant domain logic into `agent_shell`. - Do not add direct worker, database, Redis, or ALT-owned non-API runtime connections to Flutter client code. - Do not make push notification or Mattermost availability a prerequisite for the base operator shell unless a dedicated push Milestone explicitly changes that boundary. diff --git a/agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md b/agent-roadmap/archive/phase/operator-surface/milestones/flutter-operator-console.md similarity index 96% rename from agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md rename to agent-roadmap/archive/phase/operator-surface/milestones/flutter-operator-console.md index 00a116d..94152ee 100644 --- a/agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md +++ b/agent-roadmap/archive/phase/operator-surface/milestones/flutter-operator-console.md @@ -11,7 +11,7 @@ ## 상태 -[검토중] +[완료] ## 구현 잠금 @@ -97,13 +97,13 @@ ## 완료 리뷰 -- 상태: 요청됨 +- 상태: 승인됨 - 요청일: 2026-05-31 - 완료 근거: `UX 계획 산출물`에 console scope, headless-first 흐름, 상태 정책, client boundary, wireframe gate, validation handoff가 정리되었고 모든 기능 Task가 체크되었다. - 리뷰 필요: - - [ ] 사용자가 완료 결과를 확인했다 - - [ ] archive 이동을 승인했다 -- 리뷰 코멘트: 현재 Milestone은 문서형 UX 계획 산출물로 완료 후보이며, 후속 구현성 작업은 `Operator Headless Workflow Validation`과 `Flutter Operator Console MVP`에서 다룬다. + - [x] 사용자가 완료 결과를 확인했다 + - [x] archive 이동을 승인했다 +- 리뷰 코멘트: 사용자 승인에 따라 완료 처리하고 archive로 이동한다. 후속 구현성 작업은 `Operator Headless Workflow Validation`과 `Flutter Operator Console MVP`에서 다룬다. ## 범위 제외 diff --git a/agent-roadmap/current.md b/agent-roadmap/current.md index cc21cbb..2dd44b0 100644 --- a/agent-roadmap/current.md +++ b/agent-roadmap/current.md @@ -7,9 +7,9 @@ ## 활성 Milestone -- [검토중] Flutter Operator Console UX Plan +- [진행중] Operator Headless Workflow Validation - Phase: `agent-roadmap/phase/operator-surface/PHASE.md` - - 경로: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` + - 경로: `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` ## 선택 규칙 diff --git a/agent-roadmap/phase/operator-surface/PHASE.md b/agent-roadmap/phase/operator-surface/PHASE.md index 6070230..0f19f03 100644 --- a/agent-roadmap/phase/operator-surface/PHASE.md +++ b/agent-roadmap/phase/operator-surface/PHASE.md @@ -19,10 +19,10 @@ Flutter client를 ALT의 공식 operator surface로 삼아 market data 상태와 - [완료] Operator Runtime Reliability Refactor - 경로: `agent-roadmap/archive/phase/operator-surface/milestones/operator-runtime-refactor.md` - 요약: Flutter operator console/headless validation 전에 API-worker lifecycle, worker execution wiring, capability reporting, client bootstrap, 원격 테스트 룰을 정리한다. -- [검토중] Flutter Operator Console UX Plan - - 경로: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` - - 요약: terminal형 콘솔이 아니라 dashboard/control surface라는 제품 의미, headless 검증 우선 원칙, 상태 정책, wireframe gate, validation handoff를 정리한 완료 후보 상태다. -- [계획] Operator Headless Workflow Validation +- [완료] Flutter Operator Console UX Plan + - 경로: `agent-roadmap/archive/phase/operator-surface/milestones/flutter-operator-console.md` + - 요약: terminal형 콘솔이 아니라 dashboard/control surface라는 제품 의미, headless 검증 우선 원칙, 상태 정책, wireframe gate, validation handoff를 정리했다. +- [진행중] Operator Headless Workflow Validation - 경로: `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` - 요약: Flutter 화면 없이 terminal/YAML 기반 운영 시나리오로 market data와 backtest 조회/실행 결과를 먼저 검증한다. - [보류] Flutter Operator Console MVP diff --git a/agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md b/agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md index 17f516d..f4e3533 100644 --- a/agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +++ b/agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md @@ -11,13 +11,12 @@ Flutter 화면 없이 ALT 운영 흐름을 terminal/YAML/log/test fixture 기반 ## 상태 -[계획] +[진행중] ## 구현 잠금 -- 상태: 잠금 -- 결정 필요: 아래 체크리스트 - - [ ] `Flutter Operator Console UX Plan`의 headless-first 시나리오와 결과 확인 기준을 승인한다. +- 상태: 해제 +- 결정 필요: 없음 ## 범위 @@ -65,7 +64,7 @@ Flutter 화면 없이 ALT 운영 흐름을 terminal/YAML/log/test fixture 기반 - 표준선(선택): 화면 구현보다 CLI/YAML/headless smoke를 먼저 만들고, 결과는 exit code와 machine-readable 또는 grep 가능한 출력으로 남긴다. - 선행 작업: Flutter Operator Console UX Plan - 후속 작업: Flutter Operator Console MVP -- 확인 필요: UX Plan의 headless 시나리오 승인 전에는 구현 잠금을 유지한다. +- 확인 필요: 없음 ## UX Plan handoff 기준 diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/code_review_cloud_G07_0.log b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/code_review_cloud_G07_0.log new file mode 100644 index 0000000..a0099ce --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/code_review_cloud_G07_0.log @@ -0,0 +1,208 @@ + + +# Code Review Reference - UX_SCOPE + +> **[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. +> 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-31 +task=m-flutter-operator-console/01_ux_scope_gate, plan=0, tag=UX_SCOPE + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Task ids: + - `scope`: Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. + - `boundary`: Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. + - `wireframe-gate`: 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +- Completion mode: check-on-pass + +## 이 파일을 읽는 리뷰 에이전트에게 + +> **[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-flutter-operator-console/01_ux_scope_gate/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. +4. PASS이고 task group이 `m-flutter-operator-console`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다. +5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다. + +--- + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [UX_SCOPE-1] Scope And Non-Scope | [x] | +| [UX_SCOPE-2] Boundary And Wireframe Gate | [x] | + +## 구현 체크리스트 + +- [x] `flutter-operator-console.md`에서 operator console의 제품 의미, MVP 범위, 비범위를 concise하게 고정하고 `[scope]` 완료 조건을 충족한다. +- [x] `flutter-operator-console.md`에서 Riverpod/go_router, feature-first 구조, `AltSocketClient`, generated/mapped contracts 결합 기준을 정리하고 `[boundary]` 완료 조건을 충족한다. +- [x] `flutter-operator-console.md`와 `flutter-operator-console-mvp.md`에서 wireframe 준비/사용자 승인을 후속 화면 구현 잠금 해제 조건으로 명확히 맞추고 `[wireframe-gate]` 완료 조건을 충족한다. +- [x] 원격 또는 cloud 실행 환경에서 최종 검증 명령을 실행하고 실제 stdout/stderr를 review stub에 기록한다. +- [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`로 아카이브한다. +- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다. +- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다. +- [x] PASS이면 active task 디렉터리 `agent-task/m-flutter-operator-console/01_ux_scope_gate/`를 `agent-task/archive/YYYY/MM/m-flutter-operator-console/01_ux_scope_gate/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다. +- [x] PASS이고 task group이 `m-flutter-operator-console`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다. +- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-flutter-operator-console/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다. +- [ ] 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`를 남기지 않는다. +- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다. + +## 계획 대비 변경 사항 + +- `flutter-operator-console.md`에는 scope, boundary, wireframe gate를 포함한 UX 계획 산출물 섹션을 추가했다. +- `flutter-operator-console-mvp.md`는 기존 구현 잠금과 확인 필요 항목이 이미 wireframe 승인 gate와 일치해 수정하지 않았다. +- 원격 macOS host의 기본 PATH에는 `rg`가 없어, private testing rule의 실제 checkout 환경인 원격 `code-server` 컨테이너에서 검증 명령을 실행했다. + +## 주요 설계 결정 + +- Operator console은 terminal UI가 아니라 API 서버 중심 dashboard/control surface로 고정했다. +- MVP 화면 범위는 market data 상태, backtest run 요청/상태/result 요약, connection/disconnected 상태 노출로 제한했다. +- Riverpod/go_router/AltSocketClient/generated contracts의 책임을 presentation widget 밖 boundary로 남겼다. +- 후속 Flutter MVP는 headless validation 결과와 wireframe 준비/승인 전까지 잠금을 유지한다. + +## 사용자 리뷰 요청 + +_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._ + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- `[scope]`, `[boundary]`, `[wireframe-gate]`만 완료 처리했는지 확인한다. +- 실제 Flutter 화면 구현, chart/form layout, production endpoint 가정이 추가되지 않았는지 확인한다. +- MVP Milestone의 `구현 잠금`이 wireframe 준비/사용자 승인 조건을 유지하는지 확인한다. + +## 검증 결과 + +_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._ + +필수 규칙: +- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다. +- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다. +- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다. +- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다. + +### UX_SCOPE-1 중간 검증 +```bash +$ rg --sort path -n "\\[x\\] \\[scope\\]|dashboard/control surface|terminal UI|실제 Flutter production 화면" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:24:- dashboard/control surface가 필요한 이유와 아직 구현하지 않을 화면 범위 정의 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:37:- [x] [scope] Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:48:- Operator console은 terminal UI가 아니라 API 서버를 control plane으로 삼는 dashboard/control surface다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:110:- 실제 Flutter production 화면 구현 +``` + +### UX_SCOPE-2 중간 검증 +```bash +$ rg --sort path -n "\\[x\\] \\[(boundary|wireframe-gate)\\]|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:16:## 구현 잠금 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:28:- Riverpod/go_router app shell과 client integration boundary 기준 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:29:- 화면 MVP로 넘어가기 위한 wireframe 준비/승인 기준 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:35:실화면 구현 전에 operator dashboard가 왜 필요한지, 화면 없이 무엇을 먼저 검증할지, 어떤 조건에서 화면 구현 잠금을 풀지 정의한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:40:- [x] [boundary] Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:41:- [x] [wireframe-gate] 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:51:- 비범위는 production charting 전체, mobile app store 배포, push notification, wireframe 없는 layout 확정, worker 직접 제어, 별도 TypeScript web app이다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:72:- `go_router`는 operator console의 route와 URL 구조를 소유한다. feature widget은 route path 문자열을 직접 흩뿌리지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:73:- Riverpod은 socket client, connection state, feature state, command submission state를 주입한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:74:- `AltSocketClient`는 proto-socket connection과 ALT request/response dispatch boundary를 감싼다. Presentation widget은 production endpoint, socket path, generated protobuf detail을 직접 알지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:76:- app shell, provider boundary, generated contract 연결, headless smoke support는 화면 구현 잠금을 깨는 실화면 구현으로 보지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:80:- `Flutter Operator Console MVP`의 구현 잠금은 headless validation 결과와 화면 wireframe이 준비된 뒤 해제한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:102:- 완료 근거: `UX 계획 산출물`에 console scope, headless-first 흐름, 상태 정책, client boundary, wireframe gate, validation handoff가 정리되었고 모든 기능 Task가 체크되었다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:111:- wireframe 없이 dashboard layout, chart, form 흐름을 확정하는 작업 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:120:- 표준선(선택): 운영 기능은 화면보다 headless 검증을 먼저 만든다. Flutter는 feature-first 구조를 따르고, `go_router`는 화면 이동과 URL 구조, Riverpod은 API client/socket state/feature state 주입을 담당한다. Presentation widget은 production endpoint나 socket path를 직접 알지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:10:승인된 `Flutter Operator Console UX Plan`과 `Operator Headless Workflow Validation` 결과를 기준으로 Flutter client에 operator dashboard MVP를 구현한다. 화면은 headless 검증으로 확인된 운영 흐름과 준비된 wireframe을 따라가며, terminal UI나 고급 charting이 아니라 반복 운영에 필요한 조회/실행 표면을 우선한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:16:## 구현 잠금 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:21: - [ ] 화면 wireframe 또는 동등한 화면 정의 산출물이 준비되었고 사용자가 승인했다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:36:headless 검증과 wireframe 승인을 거친 운영 흐름만 실제 Flutter 화면과 provider 경계로 옮긴다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:60:- wireframe 승인 없이 실화면을 구현하는 작업 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:69:- 표준선(선택): `go_router`는 화면 이동/URL 구조, Riverpod은 API client/socket state/feature state 주입을 담당한다. UI는 `AltSocketClient` provider와 generated/mapped contracts boundary를 통해 API만 바라본다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:70:- 선행 작업: Flutter Operator Console UX Plan, Operator Headless Workflow Validation, wireframe 승인 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:72:- 확인 필요: headless 검증 완료와 wireframe 승인 전에는 구현 잠금을 유지한다. +``` + +### 최종 검증 +```bash +$ git diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +(no output; exit 0, executed in remote code-server checkout with `git -c safe.directory=/config/workspace/alt diff --check -- ...`) + +$ rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:16:## 구현 잠금 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:24:- dashboard/control surface가 필요한 이유와 아직 구현하지 않을 화면 범위 정의 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:28:- Riverpod/go_router app shell과 client integration boundary 기준 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:29:- 화면 MVP로 넘어가기 위한 wireframe 준비/승인 기준 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:35:실화면 구현 전에 operator dashboard가 왜 필요한지, 화면 없이 무엇을 먼저 검증할지, 어떤 조건에서 화면 구현 잠금을 풀지 정의한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:37:- [x] [scope] Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:40:- [x] [boundary] Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:41:- [x] [wireframe-gate] 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:48:- Operator console은 terminal UI가 아니라 API 서버를 control plane으로 삼는 dashboard/control surface다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:51:- 비범위는 production charting 전체, mobile app store 배포, push notification, wireframe 없는 layout 확정, worker 직접 제어, 별도 TypeScript web app이다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:72:- `go_router`는 operator console의 route와 URL 구조를 소유한다. feature widget은 route path 문자열을 직접 흩뿌리지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:73:- Riverpod은 socket client, connection state, feature state, command submission state를 주입한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:74:- `AltSocketClient`는 proto-socket connection과 ALT request/response dispatch boundary를 감싼다. Presentation widget은 production endpoint, socket path, generated protobuf detail을 직접 알지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:76:- app shell, provider boundary, generated contract 연결, headless smoke support는 화면 구현 잠금을 깨는 실화면 구현으로 보지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:80:- `Flutter Operator Console MVP`의 구현 잠금은 headless validation 결과와 화면 wireframe이 준비된 뒤 해제한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:102:- 완료 근거: `UX 계획 산출물`에 console scope, headless-first 흐름, 상태 정책, client boundary, wireframe gate, validation handoff가 정리되었고 모든 기능 Task가 체크되었다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:111:- wireframe 없이 dashboard layout, chart, form 흐름을 확정하는 작업 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:120:- 표준선(선택): 운영 기능은 화면보다 headless 검증을 먼저 만든다. Flutter는 feature-first 구조를 따르고, `go_router`는 화면 이동과 URL 구조, Riverpod은 API client/socket state/feature state 주입을 담당한다. Presentation widget은 production endpoint나 socket path를 직접 알지 않는다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:10:승인된 `Flutter Operator Console UX Plan`과 `Operator Headless Workflow Validation` 결과를 기준으로 Flutter client에 operator dashboard MVP를 구현한다. 화면은 headless 검증으로 확인된 운영 흐름과 준비된 wireframe을 따라가며, terminal UI나 고급 charting이 아니라 반복 운영에 필요한 조회/실행 표면을 우선한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:16:## 구현 잠금 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:21: - [ ] 화면 wireframe 또는 동등한 화면 정의 산출물이 준비되었고 사용자가 승인했다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:36:headless 검증과 wireframe 승인을 거친 운영 흐름만 실제 Flutter 화면과 provider 경계로 옮긴다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:60:- wireframe 승인 없이 실화면을 구현하는 작업 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:69:- 표준선(선택): `go_router`는 화면 이동/URL 구조, Riverpod은 API client/socket state/feature state 주입을 담당한다. UI는 `AltSocketClient` provider와 generated/mapped contracts boundary를 통해 API만 바라본다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:70:- 선행 작업: Flutter Operator Console UX Plan, Operator Headless Workflow Validation, wireframe 승인 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:72:- 확인 필요: headless 검증 완료와 wireframe 승인 전에는 구현 잠금을 유지한다. +``` + +--- + +> **[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. + +## 코드리뷰 결과 + +- 종합 판정: PASS +- 차원별 평가: + - correctness: Pass + - completeness: Pass + - test coverage: Pass + - API contract: Pass + - code quality: Pass + - plan deviation: Pass + - verification trust: Pass +- 발견된 문제: 없음 +- 다음 단계: PASS이므로 `complete.log`를 작성하고 task directory를 archive로 이동한다. diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log new file mode 100644 index 0000000..ba5b8f9 --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log @@ -0,0 +1,43 @@ +# Complete - m-flutter-operator-console/01_ux_scope_gate + +## 완료 일시 + +2026-05-31 + +## 요약 + +UX scope/gate 문서 정리 1회 루프를 PASS로 완료했다. + +## 루프 이력 + +| Plan | Review | Verdict | 메모 | +|------|--------|---------|------| +| `plan_cloud_G07_0.log` | `code_review_cloud_G07_0.log` | PASS | scope, boundary, wireframe gate 문서 산출물과 원격 검증 증거가 충족되었다. | + +## 구현/정리 내용 + +- `Flutter Operator Console UX Plan`에 operator console의 dashboard/control surface 의미와 MVP 범위/비범위를 정리했다. +- Riverpod/go_router, `AltSocketClient`, generated/mapped contracts의 client boundary를 명시했다. +- 후속 `Flutter Operator Console MVP`가 headless validation과 wireframe 준비/승인 전까지 잠금 상태를 유지해야 함을 확인했다. + +## 최종 검증 + +- `git -c safe.directory=/config/workspace/alt diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` - PASS; 원격 code-server checkout에서 출력 없이 exit 0. +- `rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` - PASS; scope, boundary, wireframe gate와 MVP 잠금 기준이 검색되었다. + +## Roadmap Completion + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Completed task ids: + - `scope`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` + - `boundary`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` + - `wireframe-gate`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` +- Not completed task ids: 없음 + +## 잔여 Nit + +- 없음 + +## 후속 작업 + +- 없음 diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/plan_cloud_G07_0.log b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/plan_cloud_G07_0.log new file mode 100644 index 0000000..f7e505c --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/plan_cloud_G07_0.log @@ -0,0 +1,181 @@ + + +# Plan - UX_SCOPE + +## 구현 에이전트 지시 + +이 파일은 `m-flutter-operator-console/01_ux_scope_gate` 구현 계약이다. 구현 에이전트는 아래 체크리스트를 수행하고 검증 출력까지 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션에 기록한 뒤 active 파일을 유지한 채 리뷰를 요청한다. 사용자 결정, 사용자 소유 외부 환경, 범위 충돌이 있으면 review stub의 `사용자 리뷰 요청` 섹션을 채우고 중단한다. 재실행 가능한 검증 증거 공백은 사용자 리뷰 요청이 아니다. + +## 배경 + +현재 Milestone은 실화면 구현 전에 operator console의 의미와 구현 gate를 고정하는 작업이다. 사용자는 화면 구현을 최대한 늦추고, wireframe 없이 agent가 임의로 dashboard depth를 확정하지 않기를 요청했다. 이 계획은 작은 정의성 작업을 먼저 완료해 후속 headless 검증 계획의 경계를 만든다. + +## 사용자 리뷰 요청 흐름 + +구현 중 사용자만 결정할 수 있는 화면 형태, scope 확대, wireframe 승인 조건 변경이 필요하면 `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 정확한 결정, 근거, 재개 조건을 기록한다. code-review만 `USER_REVIEW.md` 작성 여부를 판단한다. + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Task ids: + - `scope`: Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. + - `boundary`: Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. + - `wireframe-gate`: 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +- Completion mode: check-on-pass + +## 분석 결과 + +### 읽은 파일 + +- `agent-ops/skills/common/plan/SKILL.md` +- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` +- `agent-ops/rules/project/rules.md` +- `agent-test/local/rules.md` +- `.gitignore` +- `agent-roadmap/current.md` +- `agent-roadmap/phase/operator-surface/PHASE.md` +- `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` + +### 테스트 환경 규칙 + +- 선택한 test_env: `local`. +- `agent-test/local/rules.md`는 존재하며 읽었다. +- 규칙상 로컬 테스트/검증은 금지이고 기본 테스트 환경은 원격이다. +- 이 작업은 roadmap 문서 변경이라 domain smoke profile은 매칭하지 않았다. +- 검증은 구현 에이전트가 원격 또는 cloud 실행 환경에서 `git diff --check`와 deterministic `rg --sort path`로 수행한다. +- agent-test 규칙은 존재하므로 `create-test`는 필요하지 않다. + +### 테스트 커버리지 공백 + +- 런타임 동작 변경 없음. 기존 unit/integration test 커버리지는 영향받지 않는다. +- 문서 gate 누락은 테스트가 아니라 roadmap/code-review 검증으로 확인한다. + +### 심볼 참조 + +- none. 코드 symbol rename/remove 없음. + +### 분할 판단 + +- split decision policy를 계획 작성 전에 평가했다. +- 공유 task group: `agent-task/m-flutter-operator-console/`. +- `01_ux_scope_gate`: scope, boundary, wireframe gate를 먼저 정의한다. 의존 없음. +- `02+01_headless_validation`: headless scenario, state policy, validation handoff를 정리한다. `01_ux_scope_gate` 완료가 선행 조건이다. +- 분할 이유: scope/gate 결정 없이 headless scenario를 확정하면 후속 Milestone 범위가 흔들린다. + +### 범위 결정 근거 + +- `apps/client/**`, `services/api/**`, `services/worker/**` 코드는 수정하지 않는다. 현재 작업은 실화면 구현과 runtime behavior 변경 전 문서 gate 정리다. +- `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md`의 세부 시나리오는 02번 계획에서 다룬다. +- wireframe 자체 작성은 제외한다. 이 작업은 wireframe 준비/승인 조건만 고정한다. + +### 빌드 등급 + +- build lane: `cloud`, grade: `G07`. +- review lane: `cloud`, grade: `G07`. +- 근거: UI/운영 경계 판단이 포함되고 로컬 검증이 금지되어 원격 증거 기록이 필요하다. + +## 구현 체크리스트 + +- [ ] `flutter-operator-console.md`에서 operator console의 제품 의미, MVP 범위, 비범위를 concise하게 고정하고 `[scope]` 완료 조건을 충족한다. +- [ ] `flutter-operator-console.md`에서 Riverpod/go_router, feature-first 구조, `AltSocketClient`, generated/mapped contracts 결합 기준을 정리하고 `[boundary]` 완료 조건을 충족한다. +- [ ] `flutter-operator-console.md`와 `flutter-operator-console-mvp.md`에서 wireframe 준비/사용자 승인을 후속 화면 구현 잠금 해제 조건으로 명확히 맞추고 `[wireframe-gate]` 완료 조건을 충족한다. +- [ ] 원격 또는 cloud 실행 환경에서 최종 검증 명령을 실행하고 실제 stdout/stderr를 review stub에 기록한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## [UX_SCOPE-1] Scope And Non-Scope + +### 문제 + +`agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:37`은 console이 dashboard/control surface라고 쓰지만, 완료 산출물이 어디에 남는지와 실화면으로 오해하지 않을 비범위가 충분히 고정되어 있지 않다. + +Before: + +```markdown +37 - [ ] [scope] Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. +``` + +### 해결 방법 + +Milestone의 `범위`, `범위 제외`, `작업 컨텍스트`를 보강하고 `[scope]`를 완료 처리한다. 비범위는 실제 Flutter production 화면, wireframe 없는 dashboard depth 확정, chart/form layout 확정으로 제한한다. + +After 방향: + +```markdown +- [x] [scope] Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. +``` + +### 수정 파일 및 체크리스트 + +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md`의 `범위`와 `범위 제외`를 보강한다. +- [ ] `[scope]` task를 `[x]`로 바꾼다. + +### 테스트 작성 + +테스트 작성 안 함. 코드 동작 변경이 아닌 roadmap 문서 정리다. + +### 중간 검증 + +```bash +rg --sort path -n "\\[x\\] \\[scope\\]|dashboard/control surface|terminal UI|실제 Flutter production 화면" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md +``` + +기대 결과: scope 체크와 console 의미/비범위 문구가 모두 검색된다. + +## [UX_SCOPE-2] Boundary And Wireframe Gate + +### 문제 + +`agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:40-41`과 `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md:18-21`은 boundary와 wireframe 조건을 언급하지만, 현재 Milestone 완료와 후속 MVP 잠금 조건의 연결이 review evidence로 복사될 만큼 명확하지 않다. + +Before: + +```markdown +40 - [ ] [boundary] Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. +41 - [ ] [wireframe-gate] 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +``` + +### 해결 방법 + +현재 Milestone에는 app shell과 provider boundary 원칙을 짧게 고정하고, MVP Milestone의 `구현 잠금`과 `확인 필요` 문구가 wireframe 준비/사용자 승인 없이는 해제될 수 없도록 맞춘다. + +After 방향: + +```markdown +- [x] [boundary] Riverpod/go_router app shell, feature-first 구조, `AltSocketClient`, generated/mapped contracts의 결합 기준을 정리한다. +- [x] [wireframe-gate] 후속 `Flutter Operator Console MVP`의 구현 잠금 해제 조건을 화면 wireframe 준비/승인 여부로 정리한다. +``` + +### 수정 파일 및 체크리스트 + +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md`의 `작업 컨텍스트`에 boundary 원칙을 남긴다. +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md`의 `구현 잠금`과 `확인 필요`가 wireframe 승인 gate와 일치하는지 확인하고 필요 시 보강한다. +- [ ] `[boundary]`, `[wireframe-gate]` task를 `[x]`로 바꾼다. + +### 테스트 작성 + +테스트 작성 안 함. 코드 동작 변경이 아닌 roadmap gate 정리다. + +### 중간 검증 + +```bash +rg --sort path -n "\\[x\\] \\[(boundary|wireframe-gate)\\]|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +``` + +기대 결과: boundary task, wireframe task, MVP 구현 잠금 조건이 모두 검색된다. + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` | UX_SCOPE-1, UX_SCOPE-2 | +| `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md` | UX_SCOPE-2 | + +## 최종 검증 + +```bash +git diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +rg --sort path -n "\\[x\\] \\[(scope|boundary|wireframe-gate)\\]|dashboard/control surface|terminal UI|go_router|Riverpod|AltSocketClient|wireframe|구현 잠금" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/flutter-operator-console-mvp.md +``` + +모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/code_review_cloud_G07_0.log b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/code_review_cloud_G07_0.log new file mode 100644 index 0000000..0a2380d --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/code_review_cloud_G07_0.log @@ -0,0 +1,246 @@ + + +# Code Review Reference - HEADLESS + +> **[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. +> 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-31 +task=m-flutter-operator-console/02+01_headless_validation, plan=0, tag=HEADLESS + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Task ids: + - `headless-first`: 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. + - `state-policy`: loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. + - `validation-handoff`: 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +- Completion mode: check-on-pass + +## 이 파일을 읽는 리뷰 에이전트에게 + +> **[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-flutter-operator-console/02+01_headless_validation/`로 이동한다. WARN/FAIL이면 user-review gate를 확인한 뒤 다음 active plan/review 파일 또는 `USER_REVIEW.md`를 작성한다. +4. PASS이고 task group이 `m-flutter-operator-console`이면 완료 이벤트 메타데이터를 보고한다. roadmap 상태 체크와 `update-roadmap` 호출은 런타임 책임이다. +5. 적용 가능한 `코드리뷰 전용 체크리스트` 항목을 최종 `.log` 위치에서 체크한 뒤 보고한다. + +--- + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [HEADLESS-1] Headless Scenario And State Policy | [x] | +| [HEADLESS-2] Validation Handoff | [x] | + +## 구현 체크리스트 + +- [x] 구현 시작 전 `agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log` 존재를 확인한다. +- [x] `flutter-operator-console.md`에서 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리하고 `[headless-first]` 완료 조건을 충족한다. +- [x] `flutter-operator-console.md`에서 loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리하고 `[state-policy]` 완료 조건을 충족한다. +- [x] `flutter-operator-console.md`와 `operator-headless-workflow-validation.md`에서 후속 validation Milestone의 terminal/YAML 시나리오와 결과 확인 기준을 맞추고 `[validation-handoff]` 완료 조건을 충족한다. +- [x] 원격 또는 cloud 실행 환경에서 최종 검증 명령을 실행하고 실제 stdout/stderr를 review stub에 기록한다. +- [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`로 아카이브한다. +- [x] `.gitignore`의 Agent-Ops 관리 block이 `agent-task/**/*.md`와 `agent-task/**/*.log`를 unignore하여 plan/review/archive 산출물이 추적 가능한지 확인한다. +- [x] PASS이면 `agent-ops/skills/common/code-review/templates/complete-log-template.md` 기준으로 `complete.log`를 작성하고 active `.md` 파일을 남기지 않는다. +- [x] PASS이면 active task 디렉터리 `agent-task/m-flutter-operator-console/02+01_headless_validation/`를 `agent-task/archive/YYYY/MM/m-flutter-operator-console/02+01_headless_validation/`로 이동하고 최종 archive 경로에서 이 체크리스트를 갱신한다. +- [x] PASS이고 task group이 `m-flutter-operator-console`이면 런타임이 읽을 완료 이벤트 메타데이터를 보고하고, roadmap 수정이나 `update-roadmap` 직접 호출을 하지 않는다. +- [x] PASS split 작업이면 이동 후 빈 active parent `agent-task/m-flutter-operator-console/`를 제거하거나, 남은 sibling/file이 있어 유지했다고 확인한다. +- [ ] 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`를 남기지 않는다. +- [ ] USER_REVIEW가 사용자 결정으로 완료/PASS 해소되면 `USER_REVIEW.md`를 해소 상태로 갱신하고 `complete.log`를 작성한 뒤 task directory를 archive로 이동한다. + +## 계획 대비 변경 사항 + +- `01_ux_scope_gate`는 code-review PASS로 `agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log`에 archive되었다. split 규칙상 archived predecessor `complete.log`가 유효하므로 의존성 검증 명령은 active 경로 대신 archive 경로로 대체했다. +- 원격 macOS host의 기본 PATH에는 `rg`가 없어, private testing rule의 실제 checkout 환경인 원격 `code-server` 컨테이너에서 검증 명령을 실행했다. +- 실제 CLI/YAML parser 또는 smoke runner 구현은 만들지 않고, 후속 Milestone이 인수할 scenario/result 기준만 문서화했다. + +## 주요 설계 결정 + +- Headless-first 흐름은 API connection smoke, market data status, backtest request/polling/result, invalid request matrix로 분리했다. +- 상태 정책은 loading/empty/error/unavailable/disconnected별 terminal 표현 기준과 operator action 가능/불가 기준으로 남겼다. +- `Operator Headless Workflow Validation`에는 scenario별 command/input/output/exit code/evidence 기준을 인수 테이블로 보강했다. + +## 사용자 리뷰 요청 + +_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다. 후속 에이전트가 명령 재실행이나 산출물 수집으로 해소할 수 있는 검증 증거 공백만으로는 사용자 리뷰 요청을 작성하지 않는다._ + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- `01_ux_scope_gate`의 `complete.log`가 구현 시작 전 존재했는지 확인한다. +- `[headless-first]`, `[state-policy]`, `[validation-handoff]`만 완료 처리했는지 확인한다. +- 실제 CLI/YAML parser 구현이나 Flutter 화면 구현으로 범위가 확장되지 않았는지 확인한다. +- 후속 `Operator Headless Workflow Validation` Milestone과 handoff 기준이 충돌하지 않는지 확인한다. + +## 검증 결과 + +_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._ + +필수 규칙: +- 검증 명령은 고정된 계약이다. 임의로 대체하지 않는다. +- 대체가 필요하면 `계획 대비 변경 사항`에 이유와 대체 명령을 기록한다. +- `검증 결과`에는 실제 stdout/stderr를 붙여 넣는다. +- 사용자 리뷰 요청으로 명령을 끝까지 실행하지 못했다면 `사용자 리뷰 요청`에 실행한 명령, 실제 출력, 미실행 명령의 사유를 기록한다. + +### HEADLESS 의존성 검증 +```bash +$ test -f agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log +대체 명령: +$ test -f agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log +(no output; exit 0, executed in remote code-server checkout) +``` + +### HEADLESS-1 중간 검증 +```bash +$ rg --sort path -n "\\[x\\] \\[(headless-first|state-policy)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:26:- loading/empty/error/unavailable/disconnected 상태 정책 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:27:- 실행 요청 입력, 검증, 실패 응답을 YAML/terminal 결과로 먼저 확인하는 정책 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:38:- [x] [headless-first] 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:39:- [x] [state-policy] loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:55:- 화면 구현 전에 API connection smoke, capability 조회, market data 상태 조회, backtest 실행 요청, run 상태 폴링, result 요약 조회, 실패 응답 표현을 CLI 또는 terminal output으로 확인한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:56:- 실행 요청 입력은 YAML scenario로 고정하고, 성공/실패 기대값은 log 또는 test fixture에서 재현 가능해야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:57:- Flutter 화면은 headless 검증에서 확인된 요청/응답 shape와 상태 전이를 소비한다. 화면이 아직 없는 동안에도 운영 흐름의 입력, 출력, 실패 이유는 terminal에서 읽을 수 있어야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:64:| loading | 요청 시작, 응답 대기, run polling 중임을 단계와 함께 출력한다. | 같은 대상 중복 실행은 막고 refresh/cancel 가능 여부만 명시한다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:65:| empty | 조회는 성공했지만 market data, run, result가 없는 상태를 출력한다. | import/backtest 실행처럼 다음 생성 action이 있으면 활성화한다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:66:| error | 요청 실패, validation 실패, worker 실패를 구분하고 correlation id 또는 run id가 있으면 함께 출력한다. | 입력 수정이나 retry 가능한 action만 허용하고 파괴적 재시도는 요구하지 않는다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:67:| unavailable | capability 미지원, worker 미준비, 외부 provider 미설정처럼 현재 환경에서 불가능한 이유를 출력한다. | 해당 action은 비활성화하고 필요한 설정이나 선행 흐름을 안내 가능한 데이터로 남긴다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:68:| disconnected | socket 연결 없음, reconnecting, handshake 실패를 구분해 출력한다. | API 의존 action은 비활성화하고 reconnect 또는 diagnostic action만 남긴다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:81:- Wireframe은 navigation, market data status panel, backtest request form, run list/detail, result summary, loading/empty/error/unavailable/disconnected 표현을 포함해야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:87:후속 `Operator Headless Workflow Validation` Milestone은 아래 시나리오를 terminal/YAML 기반으로 구체화한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:90:- `market_data_status_query`: symbol/date range 입력으로 market data availability와 empty/unavailable 상태 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:91:- `backtest_run_request`: YAML scenario의 strategy, symbol universe, date range, initial capital 입력 검증과 run 생성 응답 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:93:- `backtest_result_summary`: completed run의 summary metrics, empty result, missing run id 에러 확인. +``` + +### HEADLESS-2 중간 검증 +```bash +$ rg --sort path -n "\\[x\\] \\[validation-handoff\\]|Operator Headless Workflow Validation|scenario|terminal|YAML|result|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:27:- 실행 요청 입력, 검증, 실패 응답을 YAML/terminal 결과로 먼저 확인하는 정책 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:42:- [x] [validation-handoff] 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:56:- 실행 요청 입력은 YAML scenario로 고정하고, 성공/실패 기대값은 log 또는 test fixture에서 재현 가능해야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:57:- Flutter 화면은 headless 검증에서 확인된 요청/응답 shape와 상태 전이를 소비한다. 화면이 아직 없는 동안에도 운영 흐름의 입력, 출력, 실패 이유는 terminal에서 읽을 수 있어야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:87:후속 `Operator Headless Workflow Validation` Milestone은 아래 시나리오를 terminal/YAML 기반으로 구체화한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:91:- `backtest_run_request`: YAML scenario의 strategy, symbol universe, date range, initial capital 입력 검증과 run 생성 응답 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:96:각 시나리오는 command, input fixture, expected terminal/log output, exit status, 확인할 protobuf/view-model field를 함께 남겨 Flutter MVP가 같은 상태 정책을 소비할 수 있어야 한다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:1:# Milestone: Operator Headless Workflow Validation +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:10:Flutter 화면 없이 ALT 운영 흐름을 terminal/YAML/log/test fixture 기반으로 먼저 검증한다. market data와 backtest 조회/실행 경로가 화면 없이도 구성, 실행, 결과 확인이 가능해진 뒤에만 operator dashboard 화면 구현 후보로 넘긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:24:- YAML 또는 동등한 파일 기반 operator scenario 정의 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:25:- CLI/terminal entrypoint에서 scenario 실행 또는 조회 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:28:- unavailable/error/disconnected 결과의 machine-readable 또는 grep 가능한 출력 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:30:- `api_connection_smoke`, `market_data_status_query`, `backtest_run_request`, `backtest_run_polling`, `backtest_result_summary`, `invalid_request_matrix` 시나리오의 command/input/output/exit code 기준 확정 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:38:- [ ] [scenario-format] operator scenario를 YAML 또는 동등한 파일 형식으로 표현한다. 검증: 예시 scenario가 parser 또는 dry-run 검증을 통과한다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:39:- [ ] [terminal-run] terminal에서 scenario를 실행하거나 대표 조회를 수행할 수 있다. 검증: CLI 또는 script가 exit code와 요약 출력을 남긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:65:- 표준선(선택): 화면 구현보다 CLI/YAML/headless smoke를 먼저 만들고, 결과는 exit code와 machine-readable 또는 grep 가능한 출력으로 남긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:76:| `api_connection_smoke` | API socket host/path와 optional reconnect 설정 | handshake/capability, disconnected/reconnect 실패, exit code | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:83:각 scenario는 command, YAML 또는 동등 fixture, expected terminal/log output, exit code, 확인할 protobuf 또는 view-model field를 evidence로 남긴다. +``` + +### 최종 검증 +```bash +$ test -f agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log +대체 명령: +$ test -f agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log +(no output; exit 0, executed in remote code-server checkout) + +$ git diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +(no output; exit 0, executed in remote code-server checkout with `git -c safe.directory=/config/workspace/alt diff --check -- ...`) + +$ rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:10:실제 Flutter 화면 구현에 들어가기 전에 operator console의 의미, headless-first 검증 순서, wireframe gate를 고정한다. 이 Milestone의 console은 terminal UI가 아니라 dashboard/control surface지만, 화면 구현은 terminal/YAML 기반 운영 검증과 wireframe 준비가 끝난 뒤로 미룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:26:- loading/empty/error/unavailable/disconnected 상태 정책 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:27:- 실행 요청 입력, 검증, 실패 응답을 YAML/terminal 결과로 먼저 확인하는 정책 +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:37:- [x] [scope] Operator console이 terminal UI가 아니라 dashboard/control surface임을 정의하고 MVP 범위와 비범위를 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:38:- [x] [headless-first] 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:39:- [x] [state-policy] loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:42:- [x] [validation-handoff] 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:48:- Operator console은 terminal UI가 아니라 API 서버를 control plane으로 삼는 dashboard/control surface다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:49:- MVP 화면은 market data 상태 조회, backtest run 요청, run 상태 조회, result 요약 조회, connection/disconnected 상태 노출에 한정한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:55:- 화면 구현 전에 API connection smoke, capability 조회, market data 상태 조회, backtest 실행 요청, run 상태 폴링, result 요약 조회, 실패 응답 표현을 CLI 또는 terminal output으로 확인한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:56:- 실행 요청 입력은 YAML scenario로 고정하고, 성공/실패 기대값은 log 또는 test fixture에서 재현 가능해야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:57:- Flutter 화면은 headless 검증에서 확인된 요청/응답 shape와 상태 전이를 소비한다. 화면이 아직 없는 동안에도 운영 흐름의 입력, 출력, 실패 이유는 terminal에서 읽을 수 있어야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:58:- 검증 결과는 후속 `Operator Headless Workflow Validation` Milestone이 인수하며, 그 Milestone은 실제 command, fixture, expected output을 확정한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:64:| loading | 요청 시작, 응답 대기, run polling 중임을 단계와 함께 출력한다. | 같은 대상 중복 실행은 막고 refresh/cancel 가능 여부만 명시한다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:65:| empty | 조회는 성공했지만 market data, run, result가 없는 상태를 출력한다. | import/backtest 실행처럼 다음 생성 action이 있으면 활성화한다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:66:| error | 요청 실패, validation 실패, worker 실패를 구분하고 correlation id 또는 run id가 있으면 함께 출력한다. | 입력 수정이나 retry 가능한 action만 허용하고 파괴적 재시도는 요구하지 않는다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:67:| unavailable | capability 미지원, worker 미준비, 외부 provider 미설정처럼 현재 환경에서 불가능한 이유를 출력한다. | 해당 action은 비활성화하고 필요한 설정이나 선행 흐름을 안내 가능한 데이터로 남긴다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:68:| disconnected | socket 연결 없음, reconnecting, handshake 실패를 구분해 출력한다. | API 의존 action은 비활성화하고 reconnect 또는 diagnostic action만 남긴다. | +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:81:- Wireframe은 navigation, market data status panel, backtest request form, run list/detail, result summary, loading/empty/error/unavailable/disconnected 표현을 포함해야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:87:후속 `Operator Headless Workflow Validation` Milestone은 아래 시나리오를 terminal/YAML 기반으로 구체화한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:89:- `api_connection_smoke`: API socket connect, handshake/capability 조회, disconnected/reconnect 실패 표현 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:90:- `market_data_status_query`: symbol/date range 입력으로 market data availability와 empty/unavailable 상태 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:91:- `backtest_run_request`: YAML scenario의 strategy, symbol universe, date range, initial capital 입력 검증과 run 생성 응답 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:93:- `backtest_result_summary`: completed run의 summary metrics, empty result, missing run id 에러 확인. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:96:각 시나리오는 command, input fixture, expected terminal/log output, exit status, 확인할 protobuf/view-model field를 함께 남겨 Flutter MVP가 같은 상태 정책을 소비할 수 있어야 한다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:106:- 리뷰 코멘트: 현재 Milestone은 문서형 UX 계획 산출물로 완료 후보이며, 후속 구현성 작업은 `Operator Headless Workflow Validation`과 `Flutter Operator Console MVP`에서 다룬다. +agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:122:- 후속 작업: Operator Headless Workflow Validation, Flutter Operator Console MVP, Flutter Push Notification Boundary +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:1:# Milestone: Operator Headless Workflow Validation +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:10:Flutter 화면 없이 ALT 운영 흐름을 terminal/YAML/log/test fixture 기반으로 먼저 검증한다. market data와 backtest 조회/실행 경로가 화면 없이도 구성, 실행, 결과 확인이 가능해진 뒤에만 operator dashboard 화면 구현 후보로 넘긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:24:- YAML 또는 동등한 파일 기반 operator scenario 정의 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:25:- CLI/terminal entrypoint에서 scenario 실행 또는 조회 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:28:- unavailable/error/disconnected 결과의 machine-readable 또는 grep 가능한 출력 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:30:- `api_connection_smoke`, `market_data_status_query`, `backtest_run_request`, `backtest_run_polling`, `backtest_result_summary`, `invalid_request_matrix` 시나리오의 command/input/output/exit code 기준 확정 +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:38:- [ ] [scenario-format] operator scenario를 YAML 또는 동등한 파일 형식으로 표현한다. 검증: 예시 scenario가 parser 또는 dry-run 검증을 통과한다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:39:- [ ] [terminal-run] terminal에서 scenario를 실행하거나 대표 조회를 수행할 수 있다. 검증: CLI 또는 script가 exit code와 요약 출력을 남긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:42:- [ ] [error-output] unavailable/error/disconnected 상태가 화면 없이도 판별 가능한 출력으로 남는다. 검증: typed error 또는 상태 코드 출력 테스트가 통과한다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:65:- 표준선(선택): 화면 구현보다 CLI/YAML/headless smoke를 먼저 만들고, 결과는 exit code와 machine-readable 또는 grep 가능한 출력으로 남긴다. +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:76:| `api_connection_smoke` | API socket host/path와 optional reconnect 설정 | handshake/capability, disconnected/reconnect 실패, exit code | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:77:| `market_data_status_query` | symbol, date range, provider/capability option | availability, empty, unavailable 상태와 grep 가능한 status key | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:78:| `backtest_run_request` | strategy, symbol universe, date range, initial capital | validation success/failure, run id, typed error key | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:80:| `backtest_result_summary` | completed run id | summary metrics, empty result, missing run id error | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:81:| `invalid_request_matrix` | 필수 입력 누락 또는 잘못된 symbol/date/capital/capability | validation error, unavailable/error 구분, non-zero exit code | +agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md:83:각 scenario는 command, YAML 또는 동등 fixture, expected terminal/log output, exit code, 확인할 protobuf 또는 view-model field를 evidence로 남긴다. +``` + +--- + +> **[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. + +## 코드리뷰 결과 + +- 종합 판정: PASS +- 차원별 평가: + - correctness: Pass + - completeness: Pass + - test coverage: Pass + - API contract: Pass + - code quality: Pass + - plan deviation: Pass + - verification trust: Pass +- 발견된 문제: 없음 +- 다음 단계: PASS이므로 `complete.log`를 작성하고 task directory를 archive로 이동한다. diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/complete.log b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/complete.log new file mode 100644 index 0000000..7b58c05 --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/complete.log @@ -0,0 +1,44 @@ +# Complete - m-flutter-operator-console/02+01_headless_validation + +## 완료 일시 + +2026-05-31 + +## 요약 + +Headless validation handoff 문서 정리 1회 루프를 PASS로 완료했다. + +## 루프 이력 + +| Plan | Review | Verdict | 메모 | +|------|--------|---------|------| +| `plan_cloud_G07_0.log` | `code_review_cloud_G07_0.log` | PASS | headless-first 흐름, 상태 정책, validation handoff 기준과 원격 검증 증거가 충족되었다. | + +## 구현/정리 내용 + +- `Flutter Operator Console UX Plan`에 CLI/terminal/YAML/log/test fixture 기반 headless-first 운영 흐름을 정리했다. +- loading/empty/error/unavailable/disconnected 상태별 terminal 표현과 operator action 가능/불가 정책을 정리했다. +- `Operator Headless Workflow Validation`에 scenario별 command/input/output/exit code/evidence 기준을 인수 가능한 형태로 보강했다. + +## 최종 검증 + +- `test -f agent-task/archive/2026/05/m-flutter-operator-console/01_ux_scope_gate/complete.log` - PASS; 원격 code-server checkout에서 출력 없이 exit 0. +- `git -c safe.directory=/config/workspace/alt diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` - PASS; 원격 code-server checkout에서 출력 없이 exit 0. +- `rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` - PASS; headless task 체크, 상태 정책, handoff scenario 기준이 검색되었다. + +## Roadmap Completion + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Completed task ids: + - `headless-first`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` + - `state-policy`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` + - `validation-handoff`: PASS; evidence=`plan_cloud_G07_0.log`, `code_review_cloud_G07_0.log`; verification=`rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` +- Not completed task ids: 없음 + +## 잔여 Nit + +- 없음 + +## 후속 작업 + +- 없음 diff --git a/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/plan_cloud_G07_0.log b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/plan_cloud_G07_0.log new file mode 100644 index 0000000..9ebb3d9 --- /dev/null +++ b/agent-task/archive/2026/05/m-flutter-operator-console/02+01_headless_validation/plan_cloud_G07_0.log @@ -0,0 +1,190 @@ + + +# Plan - HEADLESS + +## 구현 에이전트 지시 + +이 파일은 `m-flutter-operator-console/02+01_headless_validation` 구현 계약이다. 이 subtask는 `01_ux_scope_gate`의 `complete.log`가 있어야 구현을 시작할 수 있다. 구현 에이전트는 아래 체크리스트를 수행하고 검증 출력까지 `CODE_REVIEW-cloud-G07.md`의 구현 에이전트 소유 섹션에 기록한 뒤 active 파일을 유지한 채 리뷰를 요청한다. + +## 배경 + +현재 Milestone은 화면 구현 전에 terminal/YAML 기반 검증 순서를 확정해야 한다. 01번 작업이 scope와 wireframe gate를 고정하면, 이 작업은 그 경계 안에서 headless scenario와 상태 표현, 후속 validation Milestone의 handoff 기준을 만든다. + +## 사용자 리뷰 요청 흐름 + +구현 중 사용자만 결정할 수 있는 operator scenario 우선순위, 화면 선행 요구, scope 확대가 필요하면 `CODE_REVIEW-cloud-G07.md`의 `사용자 리뷰 요청` 섹션에 기록한다. code-review만 `USER_REVIEW.md` 작성 여부를 판단한다. + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- Task ids: + - `headless-first`: 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. + - `state-policy`: loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. + - `validation-handoff`: 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +- Completion mode: check-on-pass + +## 분석 결과 + +### 읽은 파일 + +- `agent-ops/skills/common/plan/SKILL.md` +- `agent-ops/skills/common/_templates/implementation-user-review-request-section.md` +- `agent-ops/rules/project/rules.md` +- `agent-test/local/rules.md` +- `.gitignore` +- `agent-roadmap/current.md` +- `agent-roadmap/phase/operator-surface/PHASE.md` +- `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` +- `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` + +### 테스트 환경 규칙 + +- 선택한 test_env: `local`. +- `agent-test/local/rules.md`는 존재하며 읽었다. +- 규칙상 로컬 테스트/검증은 금지이고 기본 테스트 환경은 원격이다. +- 이 작업은 roadmap 문서 변경이라 domain smoke profile은 매칭하지 않았다. +- 검증은 구현 에이전트가 원격 또는 cloud 실행 환경에서 dependency check, `git diff --check`, deterministic `rg --sort path`로 수행한다. +- agent-test 규칙은 존재하므로 `create-test`는 필요하지 않다. + +### 테스트 커버리지 공백 + +- 런타임 동작 변경 없음. 기존 unit/integration test 커버리지는 영향받지 않는다. +- headless scenario가 아직 구현되는 것은 아니므로 실제 CLI/YAML parser test는 후속 `Operator Headless Workflow Validation`에서 다룬다. + +### 심볼 참조 + +- none. 코드 symbol rename/remove 없음. + +### 분할 판단 + +- split decision policy를 계획 작성 전에 평가했다. +- 공유 task group: `agent-task/m-flutter-operator-console/`. +- `01_ux_scope_gate`: scope, boundary, wireframe gate를 먼저 정의한다. +- `02+01_headless_validation`: 이 계획이며 predecessor `01`에 의존한다. +- predecessor 상태: 현재 active `agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log` 없음. 구현 시작 전 해당 파일이 필요하다. + +### 범위 결정 근거 + +- `apps/client/**`, `apps/cli/**`, `bin/**`, `services/api/**`, `services/worker/**` 코드는 수정하지 않는다. 이 작업은 후속 headless validation 구현의 입력을 정리한다. +- 실제 YAML schema, parser, CLI command 구현은 후속 `Operator Headless Workflow Validation`의 범위다. +- Flutter 화면 구현과 wireframe 작성은 제외한다. + +### 빌드 등급 + +- build lane: `cloud`, grade: `G07`. +- review lane: `cloud`, grade: `G07`. +- 근거: terminal/YAML workflow 정의와 원격 검증 증거가 필요하고 로컬 검증이 금지되어 있다. + +## 의존 관계 및 구현 순서 + +- 이 subtask directory 이름은 `02+01_headless_validation`이다. +- 구현 전 `agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log`가 있어야 한다. +- 의존성은 directory name의 `+01`만 따른다. 추가 의존성을 임의로 만들지 않는다. + +## 구현 체크리스트 + +- [ ] 구현 시작 전 `agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log` 존재를 확인한다. +- [ ] `flutter-operator-console.md`에서 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리하고 `[headless-first]` 완료 조건을 충족한다. +- [ ] `flutter-operator-console.md`에서 loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리하고 `[state-policy]` 완료 조건을 충족한다. +- [ ] `flutter-operator-console.md`와 `operator-headless-workflow-validation.md`에서 후속 validation Milestone의 terminal/YAML 시나리오와 결과 확인 기준을 맞추고 `[validation-handoff]` 완료 조건을 충족한다. +- [ ] 원격 또는 cloud 실행 환경에서 최종 검증 명령을 실행하고 실제 stdout/stderr를 review stub에 기록한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## [HEADLESS-1] Headless Scenario And State Policy + +### 문제 + +`agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:38-39`는 headless-first와 state-policy task를 갖고 있지만, 어떤 운영 흐름을 화면 없이 검증할지와 상태 표현이 아직 인수 가능한 형태로 정리되어 있지 않다. + +Before: + +```markdown +38 - [ ] [headless-first] 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. +39 - [ ] [state-policy] loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. +``` + +### 해결 방법 + +Milestone에 headless 검증 후보를 socket, market, backtest, error/unavailable/disconnected 흐름으로 나누어 정리한다. 상태 정책은 사람이 읽는 terminal summary와 machine-readable/grep 가능한 key를 함께 요구하도록 남긴다. + +After 방향: + +```markdown +- [x] [headless-first] 화면 구현 전 CLI, terminal output, YAML scenario, log, test fixture로 검증할 운영 흐름을 정리한다. +- [x] [state-policy] loading/empty/error/unavailable/disconnected 상태와 operator action 가능/불가 정책을 headless 결과 표현 기준으로 정리한다. +``` + +### 수정 파일 및 체크리스트 + +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md`에 headless scenario 후보를 추가한다. +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md`에 상태별 action 가능/불가 정책을 추가한다. +- [ ] `[headless-first]`, `[state-policy]` task를 `[x]`로 바꾼다. + +### 테스트 작성 + +테스트 작성 안 함. 실제 scenario parser/runner 구현은 후속 Milestone 범위다. + +### 중간 검증 + +```bash +rg --sort path -n "\\[x\\] \\[(headless-first|state-policy)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md +``` + +기대 결과: headless-first/state-policy 체크와 상태 이름이 모두 검색된다. + +## [HEADLESS-2] Validation Handoff + +### 문제 + +`agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md:42`와 `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md`가 서로 연결되어 있지만, 후속 Milestone이 받을 scenario/result 기준이 아직 충분히 구체적이지 않다. + +Before: + +```markdown +42 - [ ] [validation-handoff] 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +``` + +### 해결 방법 + +현재 Milestone에는 handoff 요약을 남기고, 후속 `Operator Headless Workflow Validation` Milestone의 범위/기능을 scenario format, terminal run, market check, backtest check, error output과 일치하게 보강한다. + +After 방향: + +```markdown +- [x] [validation-handoff] 후속 `Operator Headless Workflow Validation`이 실행할 terminal/YAML 시나리오와 결과 확인 기준을 인수 가능한 형태로 정리한다. +``` + +### 수정 파일 및 체크리스트 + +- [ ] `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md`에 validation handoff 요약을 남긴다. +- [ ] `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md`가 handoff의 scenario/result 기준과 맞는지 확인하고 필요 시 보강한다. +- [ ] `[validation-handoff]` task를 `[x]`로 바꾼다. + +### 테스트 작성 + +테스트 작성 안 함. 후속 Milestone의 구현 계획에서 CLI/YAML parser와 smoke test를 다룬다. + +### 중간 검증 + +```bash +rg --sort path -n "\\[x\\] \\[validation-handoff\\]|Operator Headless Workflow Validation|scenario|terminal|YAML|result|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +``` + +기대 결과: 현재 Milestone의 handoff와 후속 Milestone의 scenario/result 기준이 모두 검색된다. + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md` | HEADLESS-1, HEADLESS-2 | +| `agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md` | HEADLESS-2 | + +## 최종 검증 + +```bash +test -f agent-task/m-flutter-operator-console/01_ux_scope_gate/complete.log +git diff --check -- agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +rg --sort path -n "\\[x\\] \\[(headless-first|state-policy|validation-handoff)\\]|YAML|terminal|loading|empty|error|unavailable|disconnected|Operator Headless Workflow Validation|exit code|grep" agent-roadmap/phase/operator-surface/milestones/flutter-operator-console.md agent-roadmap/phase/operator-surface/milestones/operator-headless-workflow-validation.md +``` + +모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/apps/client/README.md b/apps/client/README.md index c4e697c..aa1a4d4 100644 --- a/apps/client/README.md +++ b/apps/client/README.md @@ -7,6 +7,12 @@ Generated ALT protobuf files live under `lib/src/generated/alt/v1`. Client parser map helpers live under `lib/src/contracts`. Do not edit generated files by hand; run `../../bin/contracts-gen`. +## Workbench Shell + +`lib/src/app/alt_workbench_shell.dart` provides the current ALT client shell: top titlebar, right-side activity rail, center content switching, and a right Agent dock. The dock uses the sibling `agent_shell` package as a product-neutral chat/agent surface. + +The shell is intentionally a skeleton. Quant-specific screens such as market data, backtests, portfolio, and research remain placeholders until the API/worker/domain headless paths are ready to mount real surfaces. + ```bash flutter pub get flutter run -d chrome diff --git a/apps/client/lib/src/app/alt_workbench_shell.dart b/apps/client/lib/src/app/alt_workbench_shell.dart new file mode 100644 index 0000000..3aed232 --- /dev/null +++ b/apps/client/lib/src/app/alt_workbench_shell.dart @@ -0,0 +1,368 @@ +import 'package:agent_shell/agent_shell.dart'; +import 'package:flutter/material.dart'; + +enum AltWorkbenchSection { + dashboard, + markets, + backtests, + portfolio, + research, + settings, +} + +class AltWorkbenchShell extends StatefulWidget { + final Widget dashboard; + + const AltWorkbenchShell({super.key, required this.dashboard}); + + @override + State createState() => _AltWorkbenchShellState(); +} + +class _AltWorkbenchShellState extends State { + AltWorkbenchSection _section = AltWorkbenchSection.dashboard; + bool _agentOpen = false; + + @override + Widget build(BuildContext context) { + final compactAgentDock = + _agentOpen && MediaQuery.sizeOf(context).width < 960; + return Scaffold( + backgroundColor: const Color(0xFFF6F8F7), + body: SafeArea( + child: Column( + children: [ + _AltTitleBar(section: _section), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (!compactAgentDock) Expanded(child: _buildCenterContent()), + if (_agentOpen) + SizedBox( + width: _agentPanelWidth(context), + child: const _AltAgentDock(), + ), + _AltActivityRail( + selected: _section, + agentOpen: _agentOpen, + onSelect: _select, + onToggleAgent: _toggleAgent, + ), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildCenterContent() { + return switch (_section) { + AltWorkbenchSection.dashboard => widget.dashboard, + AltWorkbenchSection.markets => const _AltPlaceholder( + icon: Icons.candlestick_chart_outlined, + title: 'Markets', + subtitle: + 'Market data import, normalization, and feed status mount here.', + ), + AltWorkbenchSection.backtests => const _AltPlaceholder( + icon: Icons.analytics_outlined, + title: 'Backtests', + subtitle: + 'Backtest run queues, reports, and scenario controls mount here.', + ), + AltWorkbenchSection.portfolio => const _AltPlaceholder( + icon: Icons.account_balance_wallet_outlined, + title: 'Portfolio', + subtitle: + 'Portfolio exposure and execution review surfaces mount here.', + ), + AltWorkbenchSection.research => const _AltPlaceholder( + icon: Icons.science_outlined, + title: 'Research', + subtitle: + 'Signals, notebooks, and experiment tracking surfaces mount here.', + ), + AltWorkbenchSection.settings => const _AltPlaceholder( + icon: Icons.tune, + title: 'Settings', + subtitle: 'API endpoint and operator workspace preferences mount here.', + ), + }; + } + + double _agentPanelWidth(BuildContext context) { + final width = MediaQuery.sizeOf(context).width; + if (width < 960) return (width - 60).clamp(0.0, 520.0); + if (width < 1120) return 360; + return 420; + } + + void _select(AltWorkbenchSection section) { + setState(() { + _section = section; + _agentOpen = false; + }); + } + + void _toggleAgent() { + setState(() { + _agentOpen = !_agentOpen; + }); + } +} + +class _AltTitleBar extends StatelessWidget { + final AltWorkbenchSection section; + + const _AltTitleBar({required this.section}); + + @override + Widget build(BuildContext context) { + return Container( + height: 52, + decoration: const BoxDecoration( + color: Color(0xFFFFFFFF), + border: Border(bottom: BorderSide(color: Color(0xFFDDE5E2))), + ), + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + children: [ + Container( + width: 28, + height: 28, + decoration: BoxDecoration( + color: const Color(0xFF006C67).withValues(alpha: 0.12), + borderRadius: BorderRadius.circular(8), + ), + child: const Icon( + Icons.show_chart, + color: Color(0xFF006C67), + size: 18, + ), + ), + const SizedBox(width: 12), + const Text( + 'ALT Console', + style: TextStyle( + color: Color(0xFF10201D), + fontWeight: FontWeight.w800, + fontSize: 16, + ), + ), + const SizedBox(width: 12), + Container(width: 1, height: 22, color: const Color(0xFFDDE5E2)), + const SizedBox(width: 12), + Expanded( + child: Text( + _sectionLabel(section), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Color(0xFF5B6B67), fontSize: 13), + ), + ), + ], + ), + ); + } +} + +class _AltActivityRail extends StatelessWidget { + final AltWorkbenchSection selected; + final bool agentOpen; + final ValueChanged onSelect; + final VoidCallback onToggleAgent; + + const _AltActivityRail({ + required this.selected, + required this.agentOpen, + required this.onSelect, + required this.onToggleAgent, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: 60, + decoration: const BoxDecoration( + color: Color(0xFFFFFFFF), + border: Border(left: BorderSide(color: Color(0xFFDDE5E2))), + ), + child: Column( + children: [ + const SizedBox(height: 8), + _RailButton( + tooltip: 'Agent', + icon: Icons.smart_toy_outlined, + selected: agentOpen, + onPressed: onToggleAgent, + ), + const Divider(color: Color(0xFFDDE5E2), height: 16), + _RailButton( + tooltip: 'Dashboard', + icon: Icons.dashboard_outlined, + selected: selected == AltWorkbenchSection.dashboard, + onPressed: () => onSelect(AltWorkbenchSection.dashboard), + ), + _RailButton( + tooltip: 'Markets', + icon: Icons.candlestick_chart_outlined, + selected: selected == AltWorkbenchSection.markets, + onPressed: () => onSelect(AltWorkbenchSection.markets), + ), + _RailButton( + tooltip: 'Backtests', + icon: Icons.analytics_outlined, + selected: selected == AltWorkbenchSection.backtests, + onPressed: () => onSelect(AltWorkbenchSection.backtests), + ), + _RailButton( + tooltip: 'Portfolio', + icon: Icons.account_balance_wallet_outlined, + selected: selected == AltWorkbenchSection.portfolio, + onPressed: () => onSelect(AltWorkbenchSection.portfolio), + ), + _RailButton( + tooltip: 'Research', + icon: Icons.science_outlined, + selected: selected == AltWorkbenchSection.research, + onPressed: () => onSelect(AltWorkbenchSection.research), + ), + const Spacer(), + _RailButton( + tooltip: 'Settings', + icon: Icons.tune, + selected: selected == AltWorkbenchSection.settings, + onPressed: () => onSelect(AltWorkbenchSection.settings), + ), + const SizedBox(height: 8), + ], + ), + ); + } +} + +class _RailButton extends StatelessWidget { + final String tooltip; + final IconData icon; + final bool selected; + final VoidCallback onPressed; + + const _RailButton({ + required this.tooltip, + required this.icon, + required this.selected, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + final color = selected ? const Color(0xFF006C67) : const Color(0xFF687A75); + return Tooltip( + message: tooltip, + waitDuration: const Duration(milliseconds: 500), + child: SizedBox( + width: 56, + height: 48, + child: IconButton( + onPressed: onPressed, + icon: Icon(icon, color: color), + style: IconButton.styleFrom( + backgroundColor: selected + ? const Color(0xFF006C67).withValues(alpha: 0.08) + : Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + ); + } +} + +class _AltAgentDock extends StatelessWidget { + const _AltAgentDock(); + + static const _messages = [ + AgentMessage( + id: 'alt-agent-intro', + role: AgentMessageRole.assistant, + text: + 'ALT agent shell is ready. Market data, backtest, portfolio, and research capabilities can be registered here.', + ), + ]; + + @override + Widget build(BuildContext context) { + return Container( + decoration: const BoxDecoration( + color: Color(0xFFFFFFFF), + border: Border(left: BorderSide(color: Color(0xFFDDE5E2))), + ), + child: const AgentShell( + messages: _messages, + placeholder: 'Ask the ALT agent', + ), + ); + } +} + +class _AltPlaceholder extends StatelessWidget { + final IconData icon; + final String title; + final String subtitle; + + const _AltPlaceholder({ + required this.icon, + required this.title, + required this.subtitle, + }); + + @override + Widget build(BuildContext context) { + return Container( + color: const Color(0xFFF6F8F7), + child: Center( + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 500), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, color: const Color(0xFF006C67), size: 40), + const SizedBox(height: 16), + Text( + title, + textAlign: TextAlign.center, + style: const TextStyle( + color: Color(0xFF10201D), + fontSize: 22, + fontWeight: FontWeight.w800, + ), + ), + const SizedBox(height: 8), + Text( + subtitle, + textAlign: TextAlign.center, + style: const TextStyle(color: Color(0xFF5B6B67), fontSize: 14), + ), + ], + ), + ), + ), + ); + } +} + +String _sectionLabel(AltWorkbenchSection section) { + return switch (section) { + AltWorkbenchSection.dashboard => 'Dashboard', + AltWorkbenchSection.markets => 'Markets', + AltWorkbenchSection.backtests => 'Backtests', + AltWorkbenchSection.portfolio => 'Portfolio', + AltWorkbenchSection.research => 'Research', + AltWorkbenchSection.settings => 'Settings', + }; +} diff --git a/apps/client/lib/src/app/router.dart b/apps/client/lib/src/app/router.dart index 3d2c408..153aca5 100644 --- a/apps/client/lib/src/app/router.dart +++ b/apps/client/lib/src/app/router.dart @@ -2,11 +2,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../features/dashboard/presentation/dashboard_screen.dart'; +import 'alt_workbench_shell.dart'; final appRouterProvider = Provider((ref) { return GoRouter( routes: [ - GoRoute(path: '/', builder: (context, state) => const DashboardScreen()), + GoRoute( + path: '/', + builder: (context, state) => const AltWorkbenchShell( + dashboard: DashboardScreen(showAppBar: false, showNavigation: false), + ), + ), ], ); }); diff --git a/apps/client/lib/src/features/dashboard/presentation/dashboard_screen.dart b/apps/client/lib/src/features/dashboard/presentation/dashboard_screen.dart index 09a7b18..380c8ed 100644 --- a/apps/client/lib/src/features/dashboard/presentation/dashboard_screen.dart +++ b/apps/client/lib/src/features/dashboard/presentation/dashboard_screen.dart @@ -4,7 +4,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:alt_client/src/integrations/socket/socket_connection_controller.dart'; class DashboardScreen extends StatelessWidget { - const DashboardScreen({super.key}); + final bool showAppBar; + final bool showNavigation; + + const DashboardScreen({ + super.key, + this.showAppBar = true, + this.showNavigation = true, + }); @override Widget build(BuildContext context) { @@ -12,10 +19,10 @@ class DashboardScreen extends StatelessWidget { builder: (context, constraints) { final wide = constraints.maxWidth >= 840; return Scaffold( - appBar: AppBar(title: const Text('ALT')), + appBar: showAppBar ? AppBar(title: const Text('ALT')) : null, body: Row( children: [ - if (wide) + if (wide && showNavigation) NavigationRail( selectedIndex: 0, destinations: const [ @@ -37,7 +44,7 @@ class DashboardScreen extends StatelessWidget { const Expanded(child: _DashboardBody()), ], ), - bottomNavigationBar: wide + bottomNavigationBar: wide || !showNavigation ? null : NavigationBar( selectedIndex: 0, diff --git a/apps/client/pubspec.lock b/apps/client/pubspec.lock index 559a769..4a38741 100644 --- a/apps/client/pubspec.lock +++ b/apps/client/pubspec.lock @@ -17,6 +17,13 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.59" + agent_shell: + dependency: "direct main" + description: + path: "../../../agent-shell" + relative: true + source: path + version: "0.1.0" analyzer: dependency: transitive description: diff --git a/apps/client/pubspec.yaml b/apps/client/pubspec.yaml index 8cd1ab4..f494e74 100644 --- a/apps/client/pubspec.yaml +++ b/apps/client/pubspec.yaml @@ -37,6 +37,10 @@ dependencies: flutter_riverpod: ^3.3.1 go_router: ^17.2.3 + # Shared embeddable agent interaction shell. + agent_shell: + path: ../../../agent-shell + # Firebase firebase_core: ^3.13.0 diff --git a/apps/client/test/app/bootstrap_test.dart b/apps/client/test/app/bootstrap_test.dart index 1310e51..5c5cb02 100644 --- a/apps/client/test/app/bootstrap_test.dart +++ b/apps/client/test/app/bootstrap_test.dart @@ -1,4 +1,3 @@ -import 'package:alt_client/src/app/app.dart'; import 'package:alt_client/src/app/bootstrap.dart'; import 'package:alt_client/src/integrations/mattermost/mattermost_auth_service.dart'; import 'package:alt_client/src/integrations/mattermost/mattermost_push_host_integration.dart'; @@ -21,7 +20,11 @@ class _FakePushClient implements MattermostPushClient { Future getDeviceToken() async => null; @override - Future setAuthToken(String serverUrl, String token, {String? identifier}) async {} + Future setAuthToken( + String serverUrl, + String token, { + String? identifier, + }) async {} @override Future setSigningKey(String serverUrl, String signingKey) async {} @@ -30,10 +33,14 @@ class _FakePushClient implements MattermostPushClient { set onDeviceTokenReady(Future Function(String token)? callback) {} @override - set onNavigateToChannel(void Function(String serverUrl, String channelId)? callback) {} + set onNavigateToChannel( + void Function(String serverUrl, String channelId)? callback, + ) {} @override - set onNavigateToThread(void Function(String serverUrl, String rootId)? callback) {} + set onNavigateToThread( + void Function(String serverUrl, String rootId)? callback, + ) {} } class _NoopAuthService implements MattermostAuthService { @@ -46,52 +53,61 @@ class _NoopAuthService implements MattermostAuthService { void main() { group('AltClientBootstrap Tests', () { - test('default bootstrapAltClient does not call Firebase or Mattermost and returns null', () async { - final host = await bootstrapAltClient( - options: const AltClientBootstrapOptions(applyFullscreen: false), - ); - expect(host, isNull); - }); + test( + 'default bootstrapAltClient does not call Firebase or Mattermost and returns null', + () async { + final host = await bootstrapAltClient( + options: const AltClientBootstrapOptions(applyFullscreen: false), + ); + expect(host, isNull); + }, + ); - test('opt-in bootstrapAltClient initializes Firebase and Mattermost push host', () async { - int firebaseInitCalls = 0; - final fakePushClient = _FakePushClient(); - final host = await bootstrapAltClient( - options: AltClientBootstrapOptions( - enablePush: true, - applyFullscreen: false, - firebaseInitializer: () async { - firebaseInitCalls += 1; + test( + 'opt-in bootstrapAltClient initializes Firebase and Mattermost push host', + () async { + int firebaseInitCalls = 0; + final fakePushClient = _FakePushClient(); + final host = await bootstrapAltClient( + options: AltClientBootstrapOptions( + enablePush: true, + applyFullscreen: false, + firebaseInitializer: () async { + firebaseInitCalls += 1; + }, + mattermostHostFactory: () { + return MattermostPushHostIntegration( + pushClient: fakePushClient, + authServiceFactory: (_) => _NoopAuthService(), + ); + }, + ), + ); + + expect(firebaseInitCalls, equals(1)); + expect(host, isNotNull); + expect(fakePushClient.initializeCalls, equals(1)); + }, + ); + + testWidgets( + 'default runAltClient renders AltClientApp shell without Firebase/push', + (tester) async { + Widget? capturedApp; + await runAltClient( + options: const AltClientBootstrapOptions(applyFullscreen: false), + runAppOverride: (app) { + capturedApp = app; }, - mattermostHostFactory: () { - return MattermostPushHostIntegration( - pushClient: fakePushClient, - authServiceFactory: (_) => _NoopAuthService(), - ); - }, - ), - ); + ); - expect(firebaseInitCalls, equals(1)); - expect(host, isNotNull); - expect(fakePushClient.initializeCalls, equals(1)); - }); + expect(capturedApp, isNotNull); + await tester.pumpWidget(capturedApp!); - testWidgets('default runAltClient renders AltClientApp shell without Firebase/push', (tester) async { - Widget? capturedApp; - await runAltClient( - options: const AltClientBootstrapOptions(applyFullscreen: false), - runAppOverride: (app) { - capturedApp = app; - }, - ); - - expect(capturedApp, isNotNull); - await tester.pumpWidget(capturedApp!); - - expect(find.text('ALT'), findsOneWidget); - expect(find.text('Backtests'), findsWidgets); - expect(find.text('Disconnected'), findsOneWidget); - }); + expect(find.text('ALT Console'), findsOneWidget); + expect(find.text('Backtests'), findsWidgets); + expect(find.text('Disconnected'), findsOneWidget); + }, + ); }); } diff --git a/apps/client/test/widget_test.dart b/apps/client/test/widget_test.dart index 12ef9ef..e9e5eb0 100644 --- a/apps/client/test/widget_test.dart +++ b/apps/client/test/widget_test.dart @@ -1,5 +1,6 @@ import 'package:alt_client/src/app/app.dart'; import 'package:alt_client/src/integrations/socket/socket_connection_controller.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -15,21 +16,28 @@ class FakeSocketConnectionController extends SocketConnectionController { } void main() { - testWidgets('shows ALT dashboard shell with default disconnected socket state', (tester) async { - await tester.pumpWidget(const ProviderScope(child: AltClientApp())); + testWidgets( + 'shows ALT dashboard shell with default disconnected socket state', + (tester) async { + await tester.pumpWidget(const ProviderScope(child: AltClientApp())); - expect(find.text('ALT'), findsOneWidget); - expect(find.text('Backtests'), findsWidgets); - expect(find.text('Korea Daily Pipeline'), findsOneWidget); - expect(find.text('Disconnected'), findsOneWidget); - }); + expect(find.text('ALT Console'), findsOneWidget); + expect(find.text('Backtests'), findsWidgets); + expect(find.text('Korea Daily Pipeline'), findsOneWidget); + expect(find.text('Disconnected'), findsOneWidget); + }, + ); - testWidgets('shows ALT dashboard with socket state Connecting', (tester) async { + testWidgets('shows ALT dashboard with socket state Connecting', ( + tester, + ) async { await tester.pumpWidget( ProviderScope( overrides: [ socketConnectionControllerProvider.overrideWith( - () => FakeSocketConnectionController(SocketConnectionState.connecting), + () => FakeSocketConnectionController( + SocketConnectionState.connecting, + ), ), ], child: const AltClientApp(), @@ -40,12 +48,15 @@ void main() { expect(find.text('Connecting'), findsOneWidget); }); - testWidgets('shows ALT dashboard with socket state Connected', (tester) async { + testWidgets('shows ALT dashboard with socket state Connected', ( + tester, + ) async { await tester.pumpWidget( ProviderScope( overrides: [ socketConnectionControllerProvider.overrideWith( - () => FakeSocketConnectionController(SocketConnectionState.connected), + () => + FakeSocketConnectionController(SocketConnectionState.connected), ), ], child: const AltClientApp(), @@ -71,4 +82,26 @@ void main() { expect(find.text('Socket Contract'), findsOneWidget); expect(find.text('Error'), findsOneWidget); }); + + testWidgets('opens ALT agent dock from the right rail', (tester) async { + await tester.pumpWidget(const ProviderScope(child: AltClientApp())); + + await tester.tap(find.byIcon(Icons.smart_toy_outlined)); + await tester.pump(); + + expect(find.text('Ask the ALT agent'), findsOneWidget); + expect(find.textContaining('ALT agent shell is ready'), findsOneWidget); + }); + + testWidgets('switches ALT workbench center content from the right rail', ( + tester, + ) async { + await tester.pumpWidget(const ProviderScope(child: AltClientApp())); + + await tester.tap(find.byIcon(Icons.candlestick_chart_outlined)); + await tester.pump(); + + expect(find.text('Markets'), findsWidgets); + expect(find.textContaining('Market data import'), findsOneWidget); + }); }