<!-- task=m-paper-trading-readiness/03+01,02_contract_api_cli_monitoring plan=0 tag=PAPER_MONITOR -->

# Plan - PAPER_MONITOR

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

구현 완료의 마지막 단계는 반드시 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채우는 것이다. 검증 명령을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 최종 판정, log rename, `complete.log`, archive 이동은 code-review-skill 전용이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 범위 충돌 없이는 안전하게 진행할 수 없으면 review stub의 `사용자 리뷰 요청` 섹션을 증거와 함께 채우고 중단한다.

## 배경

Paper runtime이 생기면 operator는 Flutter 화면 없이 API/CLI에서 paper state를 시작하고 조회할 수 있어야 한다. ALT runtime 통신 규칙상 process 간 command/query는 proto-socket과 `packages/contracts/proto`를 사용해야 한다. 이 작업은 paper monitoring surface를 contracts -> worker socket -> API forwarding -> CLI scenario까지 연결한다.

## 사용자 리뷰 요청 흐름

구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. code-review가 정당성을 검증하고 실제 `USER_REVIEW.md` 작성을 소유한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/trading-expansion/milestones/paper-trading-readiness.md`
- Task ids:
  - `paper-monitor`: API/command workflow에서 paper state를 모니터링할 수 있다.
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/trading-expansion/milestones/paper-trading-readiness.md`
- `agent-test/local/rules.md`
- `agent-test/local/contracts-smoke.md`
- `agent-test/local/api-smoke.md`
- `agent-test/local/worker-smoke.md`
- `agent-test/local/operations-smoke.md`
- `agent-ops/rules/project/domain/contracts/rules.md`
- `agent-ops/rules/project/domain/api/rules.md`
- `agent-ops/rules/project/domain/worker/rules.md`
- `agent-ops/rules/project/domain/operations/rules.md`
- `packages/contracts/proto/alt/v1/common.proto`
- `packages/contracts/proto/alt/v1/market.proto`
- `packages/contracts/proto/alt/v1/backtest.proto`
- `services/api/internal/contracts/parser_map.go`
- `services/api/internal/contracts/parser_map_test.go`
- `services/worker/internal/contracts/parser_map.go`
- `services/worker/internal/contracts/parser_map_test.go`
- `services/worker/internal/socket/backtest.go`
- `services/worker/internal/socket/backtest_mapping.go`
- `services/worker/internal/socket/backtest_mapping_test.go`
- `services/worker/internal/socket/backtest_test.go`
- `services/worker/internal/socket/handlers.go`
- `services/worker/internal/socket/server.go`
- `services/worker/internal/socket/market.go`
- `services/worker/internal/socket/market_mapping.go`
- `services/worker/internal/socket/market_test.go`
- `services/worker/internal/socket/market_mapping_test.go`
- `services/worker/internal/storage/ports.go`
- `services/worker/cmd/alt-worker/main.go`
- `services/api/internal/socket/backtest.go`
- `services/api/internal/socket/backtest_test.go`
- `services/api/internal/socket/market.go`
- `services/api/internal/socket/market_test.go`
- `services/api/internal/socket/handlers.go`
- `services/api/internal/socket/server.go`
- `services/api/internal/workerclient/client.go`
- `services/api/internal/workerclient/client_test.go`
- `apps/cli/internal/operator/client.go`
- `apps/cli/internal/operator/output.go`
- `apps/cli/internal/operator/parser_map.go`
- `apps/cli/internal/operator/parser_map_test.go`
- `apps/cli/internal/operator/runner.go`
- `apps/cli/internal/operator/runner_backtest_test.go`
- `apps/cli/internal/operator/scenario.go`
- `apps/cli/internal/operator/scenario_test.go`
- `apps/cli/internal/cli/cli.go`
- `apps/cli/cmd/alt/main.go`
- `apps/cli/testdata/operator/backtest_run_request.yaml`
- `apps/cli/testdata/operator/backtest_run_polling.yaml`
- `apps/cli/testdata/operator/backtest_result_summary.yaml`

### 테스트 환경 규칙

- test_env: `local`.
- 적용 profile: `contracts-smoke`, `api-smoke`, `worker-smoke`, `operations-smoke`.
- 적용 명령: `.proto` 변경 후 `bin/contracts-gen` 또는 `bin/contracts-check`, generated Go 변경은 `go test ./packages/contracts/gen/go/...`, API는 `go test ./services/api/...`, worker는 `go test ./services/worker/...`, CLI는 `go test ./apps/cli/...`, milestone 검증은 `bin/test`.
- 사전 확인: `bin/contracts-check`, `go test ./services/api/...`, `go test ./services/worker/...`, `go test ./apps/cli/...`, `bin/test`, `bin/lint` 실행 가능. `bin/lint` exit 0 with existing Mattermost `avoid_print` info.

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

- No contract messages exist for paper account/order/state.
- Worker/API parser maps do not register paper messages.
- Worker socket and API session handlers do not expose paper start/state requests.
- CLI scenario schema has no paper actions or output fields.

### 심볼 참조

- renamed/removed symbols: none.
- Additive protobuf fields/messages only. Existing field numbers must not change.

### 분할 판단

- split decision policy evaluated.
- This subtask directory is `03+01,02_contract_api_cli_monitoring`; predecessor indices `01` and `02` must be satisfied.
- Current state when plan was written: predecessor active plans exist, no `complete.log` yet.

### 범위 결정 근거

- Include: additive `paper_trading` contract messages, generated outputs via `bin/contracts-gen`, parser maps, worker socket handlers, API forwarding, CLI scenario actions/fixtures.
- Exclude: Flutter UI, durable DB migrations, live broker adapter, advanced risk engine, realtime/minute price feed.
- Paper state can be process-local/in-memory for readiness, as long as API/CLI can start and inspect it deterministically.

### 빌드 등급

- build: `cloud-G07`, review: `cloud-G07`.
- 근거: protobuf/schema + API/worker process boundary + CLI workflow output contract are central and have broader blast radius.

## 구현 체크리스트

- [ ] Predecessor `01_domain_paper_model` and `02+01_worker_paper_runtime` PASS `complete.log` 파일을 확인한다.
- [ ] Additive paper trading protobuf contract를 추가하고 generated outputs를 `bin/contracts-gen`으로 갱신한다.
- [ ] API/worker/CLI parser maps와 tests에 새 paper messages를 등록한다.
- [ ] Worker socket에 paper start/state handler와 process-local service dependency를 추가한다.
- [ ] API workerclient와 API socket handler에 paper forwarding을 추가한다.
- [ ] CLI scenario schema/runner/output/testdata에 paper start/state actions를 추가한다.
- [ ] `bin/contracts-check`, `go test ./packages/contracts/gen/go/... -count=1`, `go test ./services/worker/... -count=1`, `go test ./services/api/... -count=1`, `go test ./apps/cli/... -count=1`, `bin/test`, `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 의존 관계 및 구현 순서

- Depends on `01_domain_paper_model` and `02+01_worker_paper_runtime`.
- Required predecessor evidence:
  - `agent-task/m-paper-trading-readiness/01_domain_paper_model/complete.log` or matching archive path.
  - `agent-task/m-paper-trading-readiness/02+01_worker_paper_runtime/complete.log` or matching archive path.
- Do not implement until both predecessors completed.

## [PAPER_MONITOR-1] Contract Surface

### 문제

`packages/contracts/proto/alt/v1/backtest.proto:35` exposes only backtest start/read messages. Paper trading needs a separate command/query surface so operator workflow can distinguish paper account state from backtest analysis.

Current code:

```proto
// packages/contracts/proto/alt/v1/backtest.proto:35
message StartBacktestRequest {
  BacktestRunSpec spec = 1;
}
```

### 해결 방법

Add a new `packages/contracts/proto/alt/v1/paper_trading.proto` or append additive messages to an existing schema if local codegen convention requires fewer files. Prefer a new file if `bin/contracts-gen` supports it.

Minimum messages:

```proto
message StartPaperTradingRequest {
  string account_id = 1;
  BacktestRunSpec spec = 2;
  Price starting_cash = 3;
}

message StartPaperTradingResponse {
  PaperTradingState state = 1;
  ErrorInfo error = 2;
}

message GetPaperTradingStateRequest {
  string account_id = 1;
}

message GetPaperTradingStateResponse {
  PaperTradingState state = 1;
  ErrorInfo error = 2;
}

message PaperTradingState {
  string account_id = 1;
  BacktestRun run = 2;
  Price cash = 3;
  repeated BacktestPosition positions = 4;
  repeated BacktestTrade fills = 5;
  repeated BacktestEquityPoint equity_curve = 6;
}
```

Run `bin/contracts-gen`, then update parser maps in API, worker, and CLI.

### 수정 파일 및 체크리스트

- [ ] `packages/contracts/proto/alt/v1/paper_trading.proto` or `backtest.proto`.
- [ ] Generated outputs under `packages/contracts/gen/go/`.
- [ ] `services/api/internal/contracts/parser_map.go` and `_test.go`.
- [ ] `services/worker/internal/contracts/parser_map.go` and `_test.go`.
- [ ] `apps/cli/internal/operator/parser_map.go` and `_test.go`.

### 테스트 작성

- Parser map tests must assert all new request/response/state messages parse.

### 중간 검증

```bash
bin/contracts-gen
bin/contracts-check
go test ./packages/contracts/gen/go/... -count=1
```

Expected: exit 0.

## [PAPER_MONITOR-2] Worker And API Forwarding

### 문제

`services/worker/internal/socket/handlers.go:21` registers market/backtest handlers only. `services/api/internal/workerclient/client.go:31` mirrors only backtest command/query methods. There is no paper handler, dependency, or forwarding method.

Current code:

```go
// services/worker/internal/socket/handlers.go:21
handlers = append(handlers, marketHandlers(deps)...)
handlers = append(handlers, backtestHandlers(deps)...)
```

```go
// services/api/internal/workerclient/client.go:31
StartBacktest(ctx context.Context, req *altv1.StartBacktestRequest) (*altv1.StartBacktestResponse, error)
```

### 해결 방법

Worker:
- Add paper service interface to `services/worker/internal/socket.Deps`.
- Add `paperHandlers(deps)` with `StartPaperTradingRequest` and `GetPaperTradingStateRequest`.
- Add mapping helpers from worker paper snapshot to proto state.
- Add worker socket tests for validation, unavailable, success, and handler coverage.
- Wire process-local paper service in `cmd/alt-worker/main.go` after predecessor runtime exists.

API:
- Add `StartPaperTrading` and `GetPaperTradingState` to `WorkerClient`.
- Add sendTyped methods.
- Add `paperHandlers(worker)` to API session registry.
- Add handler tests for validation, forwarding, nil worker, connect failure, typed worker errors, and socket registration.

### 수정 파일 및 체크리스트

- [ ] `services/worker/internal/socket/paper.go`.
- [ ] `services/worker/internal/socket/paper_mapping.go`.
- [ ] `services/worker/internal/socket/paper_test.go`.
- [ ] `services/worker/internal/socket/handlers.go`.
- [ ] `services/worker/cmd/alt-worker/main.go`.
- [ ] `services/api/internal/workerclient/client.go`.
- [ ] `services/api/internal/workerclient/client_test.go`.
- [ ] `services/api/internal/socket/paper.go`.
- [ ] `services/api/internal/socket/paper_test.go`.
- [ ] `services/api/internal/socket/handlers.go`.

### 테스트 작성

- Worker tests: success start/state, invalid request, unavailable dependency, socket round trip.
- API tests: forwards unchanged, validation avoids worker call, connect failure maps unavailable, session registration includes new messages.

### 중간 검증

```bash
go test ./services/worker/... -count=1
go test ./services/api/... -count=1
git diff --check
```

Expected: exit 0.

## [PAPER_MONITOR-3] CLI Command Workflow

### 문제

`apps/cli/internal/operator/scenario.go:23` has no paper actions, and `apps/cli/internal/operator/runner.go` can print backtest metrics but not paper account state. Operator workflow cannot monitor paper state without Flutter.

Current code:

```go
// apps/cli/internal/operator/scenario.go:23
const (
	ActionHello Action = "hello"
	...
	ActionPollBacktestRun Action = "poll_backtest_run"
)
```

### 해결 방법

Add scenario actions:
- `start_paper_trading`
- `get_paper_trading_state`

Add request fields:
- `account_id`
- `starting_cash`

Runner behavior:
- `start_paper_trading` sends `StartPaperTradingRequest`, saves `account_id` and prints account/run/cash/trade/position counts.
- `get_paper_trading_state` sends `GetPaperTradingStateRequest` and prints stable text/JSONL fields.
- Expected status/error checks reuse existing typed ErrorInfo handling.

Add fixture:
- `apps/cli/testdata/operator/paper_trading_state.yaml`
- `apps/cli/testdata/operator/expected/paper_trading_state.jsonl`

### 수정 파일 및 체크리스트

- [ ] `apps/cli/internal/operator/scenario.go`.
- [ ] `apps/cli/internal/operator/runner.go`.
- [ ] `apps/cli/internal/operator/output.go`.
- [ ] `apps/cli/internal/operator/client.go`.
- [ ] `apps/cli/internal/operator/parser_map.go`.
- [ ] `apps/cli/internal/operator/parser_map_test.go`.
- [ ] `apps/cli/internal/operator/scenario_test.go`.
- [ ] `apps/cli/internal/operator/runner_*_test.go`.
- [ ] `apps/cli/testdata/operator/paper_trading_state.yaml`.
- [ ] `apps/cli/testdata/operator/expected/paper_trading_state.jsonl`.

### 테스트 작성

- Add parser validation tests for valid and invalid paper scenario fields.
- Add runner tests for start/state output and typed not_found error.
- Add expected JSONL fixture update.

### 중간 검증

```bash
go test ./apps/cli/... -count=1
git diff --check
```

Expected: exit 0.

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `packages/contracts/proto/alt/v1/paper_trading.proto` or `backtest.proto` | PAPER_MONITOR-1 |
| `packages/contracts/gen/go/**` | PAPER_MONITOR-1 |
| `services/api/internal/contracts/parser_map.go` | PAPER_MONITOR-1 |
| `services/api/internal/contracts/parser_map_test.go` | PAPER_MONITOR-1 |
| `services/worker/internal/contracts/parser_map.go` | PAPER_MONITOR-1 |
| `services/worker/internal/contracts/parser_map_test.go` | PAPER_MONITOR-1 |
| `apps/cli/internal/operator/parser_map.go` | PAPER_MONITOR-1, PAPER_MONITOR-3 |
| `apps/cli/internal/operator/parser_map_test.go` | PAPER_MONITOR-1, PAPER_MONITOR-3 |
| `services/worker/internal/socket/paper.go` | PAPER_MONITOR-2 |
| `services/worker/internal/socket/paper_mapping.go` | PAPER_MONITOR-2 |
| `services/worker/internal/socket/paper_test.go` | PAPER_MONITOR-2 |
| `services/worker/internal/socket/handlers.go` | PAPER_MONITOR-2 |
| `services/worker/cmd/alt-worker/main.go` | PAPER_MONITOR-2 |
| `services/api/internal/workerclient/client.go` | PAPER_MONITOR-2 |
| `services/api/internal/workerclient/client_test.go` | PAPER_MONITOR-2 |
| `services/api/internal/socket/paper.go` | PAPER_MONITOR-2 |
| `services/api/internal/socket/paper_test.go` | PAPER_MONITOR-2 |
| `services/api/internal/socket/handlers.go` | PAPER_MONITOR-2 |
| `apps/cli/internal/operator/scenario.go` | PAPER_MONITOR-3 |
| `apps/cli/internal/operator/runner.go` | PAPER_MONITOR-3 |
| `apps/cli/internal/operator/output.go` | PAPER_MONITOR-3 |
| `apps/cli/internal/operator/client.go` | PAPER_MONITOR-3 |
| `apps/cli/testdata/operator/paper_trading_state.yaml` | PAPER_MONITOR-3 |
| `apps/cli/testdata/operator/expected/paper_trading_state.jsonl` | PAPER_MONITOR-3 |

## 최종 검증

```bash
bin/contracts-gen
bin/contracts-check
go test ./packages/contracts/gen/go/... -count=1
go test ./services/worker/... -count=1
go test ./services/api/... -count=1
go test ./apps/cli/... -count=1
bin/test
git diff --check
```

Expected: all commands exit 0. `bin/lint` was pre-checked and exits 0 with existing Mattermost `avoid_print` info; run it as an additional confidence check if implementation touches lint-sensitive shared code.

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