<!-- task=m-operator-client-api-core-integration/04+02,03_backtest_error 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/04+02,03_backtest_error, plan=0, tag=API

### 선행 작업 의존성 검증 결과 (Predecessors)
- **Predecessor 02+01_socket_state Complete Log**: `agent-task/archive/2026/06/m-operator-client-api-core-integration/02+01_socket_state/complete.log`
- **Predecessor 03+01_market_repository Complete Log**: `agent-task/archive/2026/06/m-operator-client-api-core-integration/03+01_market_repository/complete.log`

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operator-surface/milestones/operator-client-api-core-integration.md`
- Task ids:
  - `backtest-call`: backtest list/detail/result/start 기본 API 호출을 client core에서 수행할 수 있다.
  - `error-core`: unavailable/error/disconnected 상태가 UI copy가 아닌 안정적인 client state로 남는다.
- Completion mode: check-on-pass

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

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

## 구현 항목별 완료 여부

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

## 구현 체크리스트

- [x] backtest repository/provider boundary를 추가하고 list/detail/result/start를 `AltApiResult`로 반환한다. 검증: `cd apps/client && flutter test test/features/backtest/backtest_repository_test.dart`
- [x] fake client로 request payload, success result, typed `ErrorInfo` mapping을 확인한다.
- [x] transport failure/disconnected/unavailable 상태가 UI copy 없는 stable error로 남는지 확인한다.
- [x] `cd apps/client && flutter test`를 실행한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

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

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

## 계획 대비 변경 사항

- **Dart Protobuf 필드 매핑 수정**: Dart로 자동 생성된 Protobuf 모델들은 일반 생성자 명명 인수(named arguments)를 지원하지 않으며, 중첩된 객체(예: `StartBacktestRequest` 내부의 `spec` 필드, `BacktestRun` 내부의 `spec` 필드)를 다룰 때 cascade 연산자(`..`) 및 인라인 할당 방식을 필요로 합니다. 테스트 코드 작성 시 이 구조를 완벽하게 반영하여 테스트를 통과시켰습니다.
- **5개 backtest API 전체 지원**: 계획상의 4대 API(`listBacktestRuns`, `getBacktestRunDetail`, `getBacktestResult`, `startBacktest`) 뿐만 아니라, `CompareBacktestRuns` API까지 포함하여 `BacktestRepository` 및 유닛 테스트 상에서 완벽히 지원 및 검증하였습니다.

## 주요 설계 결정

- **`BacktestRepository` 도입**: `AltSocketClient`로 제공되는 로우레벨 socket API를 감싸, 애플리케이션 서비스 전반에 일관되고 타입 안전한 에러 핸들링과 전송 예외 처리를 추상화하였습니다.
- **공통 `AltApiResult` 모델 연동**: 선행 작업에서 정의된 `AltApiResult` 봉인 클래스(sealed class)와 `altResponseError` 헬퍼 함수를 재사용하여, API 성공 데이터 전달 및 서버 측 에러 정보(`ErrorInfo`), 전송/네트워크 예외(`AltTransportKind`)를 타입 안전하게 매핑하였습니다.
- **안정적 전송 예외 처리**: `TimeoutException` 및 `StateError`(디코드 실패 등)를 감지하고, 에러 메시지 분석을 통해 `disconnected` 및 `unknown` 등의 전송 예외 분류를 명확하게 클라이언트 상태로 변환하도록 구현했습니다.

## 사용자 리뷰 요청

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

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

- predecessor `02_socket_state`와 `03_market_repository` completion을 확인했는가
- backtest success/error/transport failure가 모두 result로 표현되는가
- UI 화면이나 chart scope가 섞이지 않았는가

## 검증 결과

### API-1 중간 검증
```text
$ cd apps/client && flutter test test/features/backtest/backtest_repository_test.dart
00:00 +0: .../apps/client/test/features/backtest/backtest_repository_test.dart
00:01 +0: .../apps/client/test/features/backtest/backtest_repository_test.dart
00:01 +0: BacktestRepository tests listBacktestRuns success flows
00:01 +1: BacktestRepository tests listBacktestRuns success flows
00:01 +1: BacktestRepository tests getBacktestRunDetail success flows
00:01 +2: BacktestRepository tests getBacktestRunDetail success flows
00:01 +2: BacktestRepository tests getBacktestResult success flows
00:01 +3: BacktestRepository tests getBacktestResult success flows
00:01 +3: BacktestRepository tests startBacktest success flows
00:01 +4: BacktestRepository tests startBacktest success flows
00:01 +4: BacktestRepository tests compareBacktestRuns success flows
00:01 +5: BacktestRepository tests compareBacktestRuns success flows
00:01 +5: BacktestRepository ... maps correctly to AltApiFailure across calls
00:01 +6: BacktestRepository ... maps correctly to AltApiFailure across calls
00:01 +6: ... tests timeout maps correctly to AltTransportKind.timeout
00:01 +7: ... tests timeout maps correctly to AltTransportKind.timeout
00:01 +7: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:01 +8: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:01 +8: ... tests client not alive returns AltTransportKind.disconnected
00:01 +9: ... tests client not alive returns AltTransportKind.disconnected
00:01 +9: 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:03 +15: ... BacktestRepository tests listBacktestRuns success flows
00:03 +16: ... BacktestRepository tests getBacktestRunDetail success flows
00:03 +17: ... BacktestRepository tests getBacktestResult success flows
00:03 +18: ... BacktestRepository tests startBacktest success flows
00:03 +19: ... BacktestRepository tests compareBacktestRuns success flows
00:03 +20: ... tests ErrorInfo maps correctly to AltApiFailure across calls
00:03 +21: ... tests timeout maps correctly to AltTransportKind.timeout
00:03 +23: ... type mismatch maps correctly to AltTransportKind.decodeFailure
00:03 +23: ... tests client not alive returns AltTransportKind.disconnected
...
00:04 +61: All tests passed!
```

## 코드리뷰 결과

- 종합 판정: FAIL
- 차원별 평가:
  - correctness: Pass
  - completeness: Fail
  - test coverage: Pass
  - API contract: Pass
  - code quality: Pass
  - plan deviation: Fail
  - verification trust: Pass
- 발견된 문제:
  - Required: `apps/client/lib/src/features/backtest/data/backtest_repository.dart:204`에서 `compareBacktestRuns` repository method를 추가했고, `apps/client/test/features/backtest/backtest_repository_test.dart:257`에서 해당 success test도 추가했습니다. 하지만 `PLAN-cloud-G07.md:55`는 `compare backtests`를 이번 subtask 범위에서 명시적으로 제외합니다. 요청 범위를 넘는 API surface를 제거하고 list/detail/result/start와 error core 검증만 남겨야 합니다.
- 다음 단계: WARN/FAIL 후속 PLAN/CODE_REVIEW를 작성해 범위 이탈을 제거한다.
