# Plan - Client Parser Map ## 이 파일을 읽는 구현 에이전트에게 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 반드시 채운다. 검증 명령을 실행하고 실제 stdout/stderr를 기록한 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 최종화는 code-review 스킬 전용이다. ## 배경 Flutter client는 generated ALT contracts를 소비해야 하지만 현재 parser map 표준 위치가 없다. `02+01_codegen_check`가 Dart generated output을 만든 뒤, `lib/src/contracts`에 작은 helper를 두면 후속 socket client adoption이 UI와 generated code를 직접 엮지 않아도 된다. ## 분석 결과 ### 읽은 파일 - `agent-roadmap/current.md` - `agent-roadmap/phase/foundation-alignment/PHASE.md` - `agent-roadmap/phase/foundation-alignment/milestones/contract-codegen-baseline.md` - `agent-ops/rules/project/domain/client/rules.md` - `agent-ops/rules/project/domain/contracts/rules.md` - `apps/client/pubspec.yaml` - `apps/client/README.md` - `apps/client/lib/main.dart` - `apps/client/lib/src/app/app.dart` - `apps/client/lib/src/app/router.dart` - `apps/client/lib/src/features/dashboard/presentation/dashboard_screen.dart` - `apps/client/test/widget_test.dart` - `packages/contracts/proto/alt/v1/common.proto` - `packages/contracts/proto/alt/v1/market.proto` - `packages/contracts/proto/alt/v1/backtest.proto` - `../proto-socket/dart/lib/src/communicator.dart` - `bin/test` - `bin/lint` ### 테스트 커버리지 공백 - Client parser map helper: 기존 테스트 없음. 새 Dart unit test가 qualified message name keys와 fromBuffer parse success를 검증해야 한다. - Generated Dart import stability: 기존 widget test는 generated contracts를 import하지 않는다. 새 parser map test가 generated files를 컴파일 경로에 포함한다. ### 심볼 참조 - renamed/removed symbols: none. ### 분할 판단 분할 정책을 먼저 평가했다. 이 plan은 `04+02_client_parser_map`이며 `02+01_codegen_check`가 `complete.log`를 만든 뒤 시작한다. API parser map은 별도 `03+02_api_parser_map`으로 분리되어 있고, 두 subtask는 codegen 이후 병렬 가능하다. ### 범위 결정 근거 이 subtask는 `apps/client/lib/src/contracts`, generated Dart imports, client tests, client README만 다룬다. Socket connection lifecycle, WebSocket configuration, UI state, Go API 변경은 범위 밖이다. ### 빌드 등급 build=`cloud-G06`, review=`cloud-G06`. Generated Dart contracts와 proto-socket wire type conventions를 client boundary에 묶는 protocol/client 작업이다. ## 의존 관계 및 구현 순서 `04+02_client_parser_map`은 같은 task group의 `02+01_codegen_check`가 `complete.log`를 만든 뒤 시작한다. 이 의존성은 directory name의 `+02`가 source of truth다. ## 구현 체크리스트 - [ ] [API-1] Flutter client contract parser map helper와 unit test를 추가한다. - [ ] [API-2] client README에 generated contract와 parser map 표준 위치를 문서화한다. - [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. ### [API-1] Flutter parser map helper #### 문제 `apps/client/README.md:5`는 ALT protobuf bindings를 `lib/src` 아래에 추가하라고만 안내한다. `../proto-socket/dart/lib/src/communicator.dart:45`는 `Map)>` parser map을 요구하고, `../proto-socket/dart/lib/src/communicator.dart:98`은 outgoing `typeName`에 `data.info_.qualifiedMessageName`을 쓴다. Client에는 generated ALT messages의 qualified names를 모으는 helper가 없다. Before: ```markdown This app uses Riverpod for state and dependency boundaries, and `go_router` for navigation. ALT protobuf bindings and the proto-socket client layer should be added under `lib/src` after `packages/contracts` generation is introduced. ``` ```dart // ../proto-socket/dart/lib/src/communicator.dart:45 void initialize( Map)> instanceGenerator, {required Transport transport}) { _instanceGenerator = instanceGenerator; _transport = transport; } ``` 해결 후 형태: ```dart import 'package:protobuf/protobuf.dart'; Map)> altParserMap() { return { HelloRequest.getDefault().info_.qualifiedMessageName: HelloRequest.fromBuffer, HelloResponse.getDefault().info_.qualifiedMessageName: HelloResponse.fromBuffer, }; } ``` #### 해결 방법 `apps/client/lib/src/contracts/alt_contracts.dart`를 만들고 generated `common.pb.dart`, `market.pb.dart`, `backtest.pb.dart`의 request/response/result message를 등록한다. helper는 새 map을 반환하고, UI/presentation layer에는 import하지 않는다. #### 수정 파일 및 체크리스트 - [ ] `apps/client/lib/src/contracts/alt_contracts.dart`: `altParserMap()` 추가. - [ ] `apps/client/test/contracts/alt_contracts_test.dart`: qualified key와 parse success 검증. #### 테스트 작성 작성한다. `altParserMap contains generated ALT message parsers`는 `HelloRequest`, `HelloResponse`, `ListInstrumentsRequest`, `ListInstrumentsResponse`, `ListBarsRequest`, `ListBarsResponse`, `StartBacktestRequest`, `StartBacktestResponse`, `GetBacktestRunRequest`, `GetBacktestRunResponse`, `GetBacktestResultRequest`, `GetBacktestResultResponse`, `BacktestResult`를 map에서 찾아 `fromBuffer` round-trip으로 검증한다. #### 중간 검증 ```bash cd apps/client && flutter test test/contracts/alt_contracts_test.dart ``` 기대 결과: exit 0. ### [API-2] Client contract location documentation #### 문제 `apps/client/README.md:5`의 문장은 codegen 도입 전 placeholder라서 generated output path와 parser map helper 위치를 알려주지 않는다. Before: ```markdown ALT protobuf bindings and the proto-socket client layer should be added under `lib/src` after `packages/contracts` generation is introduced. ``` 해결 후 형태: ```markdown 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`. ``` #### 해결 방법 README에 generated output path, parser map helper path, regeneration command만 짧게 남긴다. #### 수정 파일 및 체크리스트 - [ ] `apps/client/README.md`: generated contract and parser map section 추가. #### 테스트 작성 문서 변경이므로 테스트 파일은 작성하지 않는다. deterministic search로 앵커 존재를 확인한다. #### 중간 검증 ```bash rg --sort path -n "lib/src/generated/alt/v1|lib/src/contracts|contracts-gen" apps/client/README.md ``` 기대 결과: 모든 앵커가 검색된다. ## 수정 파일 요약 | 파일 | 항목 | |------|------| | `apps/client/lib/src/contracts/alt_contracts.dart` | API-1 | | `apps/client/test/contracts/alt_contracts_test.dart` | API-1 | | `apps/client/README.md` | API-2 | ## 최종 검증 ```bash cd apps/client && flutter test test/contracts/alt_contracts_test.dart rg --sort path -n "lib/src/generated/alt/v1|lib/src/contracts|contracts-gen" apps/client/README.md bin/test bin/lint ``` 기대 결과: 모든 명령 exit 0. Flutter test cache output은 해당 없음. 모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.