<!-- task=m-operator-client-api-core-integration/03+01_market_repository plan=0 tag=API -->

# Code Review Reference - API

> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.**
> Fill implementation-owned sections, then stop with active files in place and report ready for review. Finalization is review-agent-only.

## 개요

date=2026-06-02
task=m-operator-client-api-core-integration/03+01_market_repository, plan=0, tag=API

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operator-surface/milestones/operator-client-api-core-integration.md`
- Task ids:
  - `market-call`: market data status/list 기본 API 호출을 client core에서 수행할 수 있다.
- Completion mode: check-on-pass

## 이 파일을 읽는 리뷰 에이전트에게

> **[REVIEW AGENT ONLY]** 종결 절차는 리뷰 에이전트 전용이다.

## 구현 항목별 완료 여부

| 항목 | 완료 여부 |
|------|---------|
| [API-1] Market repository 추가 | [x] |

## 구현 체크리스트

- [x] market repository/provider boundary를 추가하고 `listInstruments`, `listBars`를 `AltApiResult`로 반환한다. 검증: `cd apps/client && flutter test test/features/market/market_repository_test.dart`
- [x] fake client로 request payload와 parsed result/status key를 확인한다. 검증: `cd apps/client && flutter test test/features/market/market_repository_test.dart`
- [x] typed `ErrorInfo`가 `AltApiError`로 보존되는 test를 추가한다.
- [x] `cd apps/client && flutter test`를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 코드리뷰 전용 체크리스트

- [x] PASS/WARN/FAIL 판정을 append한다.
- [x] active files를 log로 archive한다.
- [x] PASS이면 `complete.log` 작성 후 archive 이동한다.
- [x] roadmap은 직접 수정하지 않는다.

## 계획 대비 변경 사항

계획상의 명세와 일치하게 구현하였으며, 특이사항 및 계획 대비 변경 사항은 없습니다. Sibling subtask인 `01_contract_mapping` 완료 상태와 결과 형태(`AltApiResult`, `AltApiError`)에 정렬하여 구현 및 검증을 완료하였습니다.

## 주요 설계 결정

1. **`MarketRepository`의 Socket wrapping 구조**: `AltSocketClient`를 wrapping하여 raw socket message 응답을 안전하게 `AltApiResult` 형태로 전환하고, server가 응답으로 반환한 `ErrorInfo`를 `AltApiError`로 매핑하여 presentation layer에 일관되게 전달합니다.
2. **연결 안정성 검증**: 소켓 클라이언트의 `isAlive` 상태를 먼저 확인하여 연결이 유실되었거나 활성화되지 않은 상황에서는 사전에 `AltTransportKind.disconnected`를 반환하도록 설계하였습니다.
3. **Transport Error 세분화**: 통신 중 발생할 수 있는 `TimeoutException`, response type mismatch (`StateError`), socket disconnected 상황과 기타 미확인 예외들을 적절한 `AltTransportKind`로 세분화하여 예외 상황의 원인을 식별하기 용이하게 구성하였습니다.

## 사용자 리뷰 요청

- 상태: 없음
- 사유 유형: 없음
- 결정 필요: 없음
- 차단 근거: 없음
- 실행한 검증/명령: 없음
- 자동 후속 불가 이유: 없음
- 재개 조건: 없음

## 리뷰어를 위한 체크포인트

- predecessor `01_contract_mapping` completion을 확인했는가
- repository가 raw protobuf error를 success처럼 반환하지 않는가
- request payload와 parsed result key가 test에 고정됐는가

## 검증 결과

### API-1 중간 검증
```text
$ cd apps/client && flutter test test/features/market/market_repository_test.dart
00:00 +0: .../alt/apps/client/test/features/market/market_repository_test.dart
00:01 +0: .../alt/apps/client/test/features/market/market_repository_test.dart
00:01 +0: MarketRepository tests listInstruments success flows parsed results
00:01 +1: MarketRepository tests listInstruments success flows parsed results
00:01 +1: MarketRepository tests listBars success flows historical data
00:01 +2: MarketRepository tests listBars success flows historical data
00:01 +2: MarketRepository ... typed ErrorInfo maps correctly to AltApiFailure
00:01 +3: MarketRepository ... typed ErrorInfo maps correctly to AltApiFailure
00:01 +3: ... tests timeout maps correctly to AltTransportKind.timeout
00:01 +4: ... tests timeout maps correctly to AltTransportKind.timeout
00:01 +4: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:01 +5: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:01 +5: ... tests client not alive returns AltTransportKind.disconnected
00:01 +6: ... tests client not alive returns AltTransportKind.disconnected
00:01 +6: All tests passed!
```

### 최종 검증
```text
$ cd apps/client && flutter test
00:00 +0: ... /config/workspace/alt/apps/client/test/app/bootstrap_test.dart
00:01 +0: ... /config/workspace/alt/apps/client/test/app/bootstrap_test.dart
00:02 +0: ... /config/workspace/alt/apps/client/test/app/bootstrap_test.dart
00:02 +0: ... does not call Firebase or Mattermost and returns null
00:02 +1: ... does not call Firebase or Mattermost and returns null
00:02 +1: ... bootstrapAltClient initializes Firebase and Mattermost push host
00:02 +2: ... bootstrapAltClient initializes Firebase and Mattermost push host
00:02 +2: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +3: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +4: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +5: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +6: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +7: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +8: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +9: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +10: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +11: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +12: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +13: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +14: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +15: ... runAltClient renders AltClientApp shell without Firebase/push
00:02 +16: ... MarketRepository tests listBars success flows historical data
00:02 +17: ... MarketRepository tests listBars success flows historical data
00:02 +17: ... tests typed ErrorInfo maps correctly to AltApiFailure
00:02 +18: ... tests typed ErrorInfo maps correctly to AltApiFailure
00:02 +18: ... tests timeout maps correctly to AltTransportKind.timeout
00:02 +19: ... tests timeout maps correctly to AltTransportKind.timeout
00:02 +19: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:02 +20: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:02 +20: ... tests client not alive returns AltTransportKind.disconnected
00:02 +21: ... tests client not alive returns AltTransportKind.disconnected
00:03 +21: ... tests client not alive returns AltTransportKind.disconnected
00:03 +21: loading /config/workspace/alt/apps/client/test/widget_test.dart
00:03 +21: ... ALT dashboard shell with default disconnected socket state
00:03 +22: ... ALT dashboard shell with default disconnected socket state
00:03 +22: /config/workspace/alt/apps/client/test/integrations/mattermost_push_host_integration_test.dart: auto-login failure does not block initialize
[MattermostHost] Mattermost auto-login failed: Bad state: credentials missing
00:03 +23: ... ALT dashboard shell with default disconnected socket state
00:03 +24: ... ALT dashboard shell with default disconnected socket state
00:03 +25: ... ALT dashboard shell with default disconnected socket state
00:03 +26: ... ALT dashboard shell with default disconnected socket state
00:03 +27: ... ALT dashboard shell with default disconnected socket state
00:03 +28: ... ALT dashboard shell with default disconnected socket state
00:03 +29: ... ALT dashboard shell with default disconnected socket state
00:03 +30: ... ALT dashboard shell with default disconnected socket state
00:03 +31: ... ALT dashboard shell with default disconnected socket state
00:03 +32: ... ALT dashboard shell with default disconnected socket state
00:03 +33: ... ALT dashboard shell with default disconnected socket state
00:03 +34: ... ALT dashboard shell with default disconnected socket state
00:03 +35: ... ALT dashboard shell with default disconnected socket state
00:03 +36: ... ALT dashboard shell with default disconnected socket state
00:03 +37: ... tests listBars market query request-response loop
00:03 +38: ... shows ALT dashboard with socket state Connecting
00:03 +39: ... shows ALT dashboard with socket state Connecting
00:03 +40: ... shows ALT dashboard with socket state Connecting
00:03 +40: ... shows ALT dashboard with socket state Connected
00:03 +41: ... shows ALT dashboard with socket state Connected
00:03 +41: ... shows ALT dashboard with socket state Error
00:03 +42: ... shows ALT dashboard with socket state Error
00:03 +42: ... opens ALT agent dock from the right rail
00:03 +43: ... opens ALT agent dock from the right rail
00:04 +43: ... opens ALT agent dock from the right rail
00:04 +44: ... opens ALT agent dock from the right rail
00:04 +45: ... opens ALT agent dock from the right rail
00:04 +46: ... opens ALT agent dock from the right rail
00:04 +47: ... opens ALT agent dock from the right rail
00:04 +48: ... opens ALT agent dock from the right rail
00:04 +49: ... opens ALT agent dock from the right rail
00:04 +50: ... opens ALT agent dock from the right rail
00:04 +51: ... opens ALT agent dock from the right rail
00:04 +51: ... switches ALT workbench center content from the right rail
00:04 +52: ... switches ALT workbench center content from the right rail
00:04 +52: All tests passed!
```

## 코드리뷰 결과

- 종합 판정: PASS
- 차원별 평가:
  - correctness: Pass
  - completeness: Pass
  - test coverage: Pass
  - API contract: Pass
  - code quality: Pass
  - plan deviation: Pass
  - verification trust: Pass
- 발견된 문제: 없음
- 다음 단계: PASS이므로 active plan/review를 log로 archive하고 `complete.log` 작성 후 task archive 이동을 수행한다.

### 리뷰어 검증

```text
$ cd apps/client && flutter test test/features/market/market_repository_test.dart
00:00 +0: loading /config/workspace/alt/apps/client/test/features/market/market_repository_test.dart
00:00 +0: MarketRepository tests listInstruments success flows parsed results
00:00 +1: MarketRepository tests listBars success flows historical data
00:00 +2: MarketRepository tests typed ErrorInfo maps correctly to AltApiFailure
00:00 +3: MarketRepository tests timeout maps correctly to AltTransportKind.timeout
00:00 +4: MarketRepository tests type mismatch maps correctly to AltTransportKind.decodeFailure
00:00 +5: MarketRepository tests client not alive returns AltTransportKind.disconnected
00:00 +6: All tests passed!
```

```text
$ cd apps/client && flutter test
00:00 +0: loading /config/workspace/alt/apps/client/test/app/bootstrap_test.dart
00:00 +1: /config/workspace/alt/apps/client/test/app/bootstrap_test.dart: AltClientBootstrap Tests opt-in bootstrapAltClient initializes Firebase and Mattermost push host
00:00 +15: /config/workspace/alt/apps/client/test/features/market/market_repository_test.dart: MarketRepository tests listInstruments success flows parsed results
00:00 +20: /config/workspace/alt/apps/client/test/features/market/market_repository_test.dart: MarketRepository tests client not alive returns AltTransportKind.disconnected
00:01 +43: /config/workspace/alt/apps/client/test/integrations/socket/socket_connection_controller_test.dart: SocketConnectionController tests successful connection and handshake
00:01 +52: All tests passed!
```

```text
$ cd apps/client && dart format --set-exit-if-changed lib/src/features/market/data/market_repository.dart test/features/market/market_repository_test.dart
Formatted test/features/market/market_repository_test.dart
Formatted 2 files (1 changed) in 0.02 seconds.
```

```text
$ cd apps/client && flutter analyze lib/src/features/market/data/market_repository.dart test/features/market/market_repository_test.dart
Analyzing 2 items...
No issues found! (ran in 2.6s)
```

```text
$ cd apps/client && flutter test test/features/market/market_repository_test.dart
00:00 +0: loading /config/workspace/alt/apps/client/test/features/market/market_repository_test.dart
00:00 +0: MarketRepository tests listInstruments success flows parsed results
00:00 +1: MarketRepository tests listBars success flows historical data
00:00 +2: MarketRepository tests typed ErrorInfo maps correctly to AltApiFailure
00:00 +3: MarketRepository tests timeout maps correctly to AltTransportKind.timeout
00:00 +4: MarketRepository tests type mismatch maps correctly to AltTransportKind.decodeFailure
00:00 +5: MarketRepository tests client not alive returns AltTransportKind.disconnected
00:00 +6: All tests passed!
```
