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
This commit is contained in:
parent
16df2d25c2
commit
1f1527d7c6
20 changed files with 1445 additions and 81 deletions
|
|
@ -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한다.
|
||||
|
||||
## 개발 흐름
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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`에서 다룬다.
|
||||
|
||||
## 범위 제외
|
||||
|
||||
|
|
@ -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`
|
||||
|
||||
## 선택 규칙
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 기준
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
<!-- task=m-flutter-operator-console/01_ux_scope_gate plan=0 tag=UX_SCOPE -->
|
||||
|
||||
# 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로 이동한다.
|
||||
|
|
@ -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
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
<!-- task=m-flutter-operator-console/01_ux_scope_gate plan=0 tag=UX_SCOPE -->
|
||||
|
||||
# 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
<!-- task=m-flutter-operator-console/02+01_headless_validation plan=0 tag=HEADLESS -->
|
||||
|
||||
# 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로 이동한다.
|
||||
|
|
@ -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
|
||||
|
||||
- 없음
|
||||
|
||||
## 후속 작업
|
||||
|
||||
- 없음
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
<!-- task=m-flutter-operator-console/02+01_headless_validation plan=0 tag=HEADLESS -->
|
||||
|
||||
# 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`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
368
apps/client/lib/src/app/alt_workbench_shell.dart
Normal file
368
apps/client/lib/src/app/alt_workbench_shell.dart
Normal file
|
|
@ -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<AltWorkbenchShell> createState() => _AltWorkbenchShellState();
|
||||
}
|
||||
|
||||
class _AltWorkbenchShellState extends State<AltWorkbenchShell> {
|
||||
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<AltWorkbenchSection> 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>[
|
||||
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',
|
||||
};
|
||||
}
|
||||
|
|
@ -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<GoRouter>((ref) {
|
||||
return GoRouter(
|
||||
routes: [
|
||||
GoRoute(path: '/', builder: (context, state) => const DashboardScreen()),
|
||||
GoRoute(
|
||||
path: '/',
|
||||
builder: (context, state) => const AltWorkbenchShell(
|
||||
dashboard: DashboardScreen(showAppBar: false, showNavigation: false),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String?> getDeviceToken() async => null;
|
||||
|
||||
@override
|
||||
Future<void> setAuthToken(String serverUrl, String token, {String? identifier}) async {}
|
||||
Future<void> setAuthToken(
|
||||
String serverUrl,
|
||||
String token, {
|
||||
String? identifier,
|
||||
}) async {}
|
||||
|
||||
@override
|
||||
Future<void> setSigningKey(String serverUrl, String signingKey) async {}
|
||||
|
|
@ -30,10 +33,14 @@ class _FakePushClient implements MattermostPushClient {
|
|||
set onDeviceTokenReady(Future<void> 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);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue