<!-- task=m-backtest-analysis-surface/03+01,02_api_client_boundary plan=0 tag=BAS-BOUNDARY -->

# Plan - BAS-BOUNDARY

## 이 파일을 읽는 구현 에이전트에게

`CODE_REVIEW-cloud-G06.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이 필수다. 구현 후 검증을 실행하고, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 사용자 결정, 외부 환경 준비, 범위 충돌이 없이는 안전하게 진행할 수 없으면 review stub의 `사용자 리뷰 요청` 섹션에 정확한 근거를 남기고 멈춘다. archive, `complete.log`, 최종 판정은 code-review 전용이다.

## 배경

Contract와 worker storage가 준비되더라도 operator client가 typed backtest query 요청을 보낼 수 없으면 analysis surface가 실제 사용 흐름으로 연결되지 않는다. 이 계획은 API parser boundary와 Flutter socket client request helpers를 좁게 연결해 run list/detail/compare 표면의 첫 호출 경계를 만든다.

## 사용자 리뷰 요청 흐름

구현 중 차단 조건은 active `CODE_REVIEW-cloud-G06.md`의 `사용자 리뷰 요청` 섹션에 기록한다. code-review가 이를 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/backtest-loop/milestones/backtest-analysis-surface.md`
- `services/api/internal/contracts/parser_map.go`
- `services/api/internal/contracts/parser_map_test.go`
- `apps/client/lib/src/contracts/alt_contracts.dart`
- `apps/client/test/contracts/alt_contracts_test.dart`
- `apps/client/lib/src/integrations/socket/alt_socket_client.dart`
- `apps/client/test/integrations/socket/alt_socket_client_test.dart`
- `packages/contracts/proto/alt/v1/backtest.proto`
- `bin/test`
- `bin/lint`
- `services/api/go.mod`
- `apps/client/pubspec.yaml`

### 테스트 커버리지 공백

- `AltSocketClient` currently tests only `hello()` request/response at `apps/client/test/integrations/socket/alt_socket_client_test.dart:113`.
- No client test sends backtest run list/detail/result/compare requests through proto-socket.
- API parser tests cover current message types only and must remain aligned with generated messages from `01_contract_surface`.

### 심볼 참조

- Renamed/removed symbols: none planned.
- New client methods will call existing inherited `sendRequest` in `AltSocketClient`, currently used by `hello()` at `apps/client/lib/src/integrations/socket/alt_socket_client.dart:32`.

### 분할 판단

- Split policy evaluated before writing plan files.
- This task depends on `01_contract_surface` and `02+01_worker_analysis_store`.
- It is separate because API/client boundary tests can be reviewed independently after schema and storage behavior exist.
- It does not create full Flutter operator UI; that belongs to later `Flutter Operator Console`.

### 범위 결정 근거

- Include API parser alignment if new messages were not already covered by `01_contract_surface`, typed client request helpers, and socket client tests.
- Exclude server-side business handlers because current API service only owns parser/socket boundary; worker owns execution and storage.
- Exclude dashboard UI and navigation.
- Exclude migrations/storage behavior already covered by `02+01_worker_analysis_store`.

### 빌드 등급

- build lane: `cloud-G06`; review lane: `cloud-G06`.
- Rationale: cross-language boundary helpers and tests, but no storage or schema design should remain by this stage.

## 구현 체크리스트

- [ ] [BAS-BOUNDARY-1] API parser map and tests include all analysis request/response messages if not already done by contracts task.
- [ ] [BAS-BOUNDARY-2] `AltSocketClient` exposes typed backtest list/detail/result/compare request helpers.
- [ ] [BAS-BOUNDARY-3] Flutter socket client tests verify request type names, payloads, and response parsing. 검증: worker/API/client 경계가 backtest result를 일관되게 다룬다.
- [ ] [BAS-BOUNDARY-4] `go test ./services/api/...`, `cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart`, `bin/test`, `bin/lint`를 실행한다. 검증: `bin/test`와 `bin/lint`가 통과한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [BAS-BOUNDARY-1] Align API parser boundary

문제: `services/api/internal/contracts/parser_map.go:19` currently registers existing backtest messages. If `01_contract_surface` added list/detail/compare messages and did not register them, API parser tests will not cover the analysis request surface.

해결 방법:

Before:

```go
19 protoSocket.TypeNameOf(&altv1.StartBacktestRequest{}):      parserFor(func() proto.Message { return &altv1.StartBacktestRequest{} }),
21 protoSocket.TypeNameOf(&altv1.GetBacktestRunRequest{}):     parserFor(func() proto.Message { return &altv1.GetBacktestRunRequest{} }),
23 protoSocket.TypeNameOf(&altv1.GetBacktestResultRequest{}):  parserFor(func() proto.Message { return &altv1.GetBacktestResultRequest{} }),
```

After: ensure `ListBacktestRuns*`, `GetBacktestRunDetail*`, and `CompareBacktestRuns*` generated messages are present in `ParserMap()` and `TestParserMapIncludesAltMessages`.

수정 파일 및 체크리스트:

- [ ] `services/api/internal/contracts/parser_map.go` includes all analysis request/response messages.
- [ ] `services/api/internal/contracts/parser_map_test.go` includes all analysis messages and round-trip parsing.

테스트 작성: update existing parser map test only.

중간 검증:

```bash
go test ./services/api/...
```

Expected: exits 0.

### [BAS-BOUNDARY-2] Add typed client request helpers

문제: `AltSocketClient.hello()` at `apps/client/lib/src/integrations/socket/alt_socket_client.dart:32` is the only typed helper. Backtest analysis requests would require callers to use raw generated messages directly.

해결 방법:

Before:

```dart
32 Future<HelloResponse> hello({Duration timeout = const Duration(seconds: 2)}) {
33   return sendRequest<HelloRequest, HelloResponse>(
```

After:

```dart
Future<ListBacktestRunsResponse> listBacktestRuns(
  ListBacktestRunsRequest request, {
  Duration timeout = const Duration(seconds: 2),
}) {
  return sendRequest<ListBacktestRunsRequest, ListBacktestRunsResponse>(
    request,
    timeout: timeout,
  );
}
```

Add equivalent helpers for `GetBacktestRunDetailRequest`, existing `GetBacktestResultRequest`, and `CompareBacktestRunsRequest`.

수정 파일 및 체크리스트:

- [ ] `apps/client/lib/src/integrations/socket/alt_socket_client.dart` imports generated `backtest.pb.dart`.
- [ ] Add `listBacktestRuns`, `getBacktestRunDetail`, `getBacktestResult`, and `compareBacktestRuns` helpers.
- [ ] Keep default timeout consistent with `hello()`.

테스트 작성: tests in BAS-BOUNDARY-3.

중간 검증:

```bash
cd apps/client && flutter analyze --no-fatal-infos
```

Expected: exits 0.

### [BAS-BOUNDARY-3] Test backtest socket helpers

문제: `apps/client/test/integrations/socket/alt_socket_client_test.dart:113` verifies hello only; no test asserts backtest request type names or response parsing over `PacketBase`.

해결 방법: Extend fake websocket tests with one helper to assert sent packet type/payload and feed a matching response packet. Cover at least list runs, run detail, get result, and compare runs.

수정 파일 및 체크리스트:

- [ ] `apps/client/test/integrations/socket/alt_socket_client_test.dart` imports generated `backtest.pb.dart`.
- [ ] Add tests for each new client helper.
- [ ] Tests assert sent `PacketBase.typeName`, serialized request fields, and parsed response fields.

테스트 작성: add focused tests in existing `AltSocketClient tests` group.

중간 검증:

```bash
cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
```

Expected: exits 0.

### [BAS-BOUNDARY-4] Boundary verification

문제: API parser, generated contract, and client helper changes must remain consistent across the workspace.

해결 방법: run focused API/client checks and full workspace smoke.

수정 파일 및 체크리스트:

- [ ] Run API parser tests.
- [ ] Run client socket helper tests.
- [ ] Run full `bin/test`.
- [ ] Run full `bin/lint`.
- [ ] Run `git diff --check`.

테스트 작성: no extra tests beyond BAS-BOUNDARY-1 and BAS-BOUNDARY-3.

중간 검증:

```bash
go test ./services/api/...
cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
bin/test
bin/lint
git diff --check
```

Expected: all commands exit 0. Go test cache output is acceptable after focused API tests pass; Flutter test output must be actual command output.

## 의존 관계 및 구현 순서

Directory dependency `03+01,02_api_client_boundary` means both predecessor task directories must produce `complete.log` before this task starts:

- `agent-task/m-backtest-analysis-surface/01_contract_surface/complete.log`
- `agent-task/m-backtest-analysis-surface/02+01_worker_analysis_store/complete.log`

Do not begin if either file is absent.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `services/api/internal/contracts/parser_map.go` | BAS-BOUNDARY-1 |
| `services/api/internal/contracts/parser_map_test.go` | BAS-BOUNDARY-1 |
| `apps/client/lib/src/integrations/socket/alt_socket_client.dart` | BAS-BOUNDARY-2 |
| `apps/client/test/integrations/socket/alt_socket_client_test.dart` | BAS-BOUNDARY-3 |

## 최종 검증

```bash
go test ./services/api/...
cd apps/client && flutter test test/integrations/socket/alt_socket_client_test.dart
bin/test
bin/lint
git diff --check
```

Expected: all commands exit 0. Go test cache output is acceptable after focused API tests pass; Flutter test output must be actual command output.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
