<!-- task=m-backtest-multi-timeframe-coverage/01_domain_capability_matrix plan=0 tag=API -->

# Plan - API

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

`CODE_REVIEW-local-G05.md`의 구현 에이전트 소유 섹션을 채우는 것이 구현의 마지막 단계다. 코드를 바꾸고 검증을 실행한 뒤 실제 구현 내용과 stdout/stderr를 리뷰 stub에 남기고, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 선택된 SDD 결정 또는 Milestone `구현 잠금 > 결정 필요` 항목이 막으면 리뷰 stub의 `사용자 리뷰 요청`만 채우고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`, `USER_REVIEW.md` 작성, log archive, `complete.log` 작성을 하지 않는다. 환경/secret/service 차단과 검증 증거 공백은 사용자 리뷰가 아니라 `검증 결과` 또는 후속 plan 대상으로 남긴다.

## 배경

`capability-matrix`는 provider, market, venue, asset type, timeframe 조합별 accepted/rejected와 거부 사유를 표현해야 한다. 현재 `ProviderCapability`는 venue/timeframe map과 daily 전용 `RequireDailyBars`만 있어 monthly/minute rejected case와 asset type 차원을 표현할 수 없다. 이 선행 plan은 domain 모델과 domain tests만 바꿔 worker/KIS rollout이 안정적으로 이어지게 한다.

## 사용자 리뷰 요청 흐름

사용자 리뷰 요청은 선택된 SDD 결정 또는 선택된 Milestone lock 결정이 실구현을 차단할 때만 active `CODE_REVIEW-local-G05.md`의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 chat 질문은 금지이며, code-review가 검증 후 실제 `USER_REVIEW.md` 작성 여부를 판단한다.

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/roadmap-sdd/SKILL.md`
- `agent-roadmap/current.md`
- `agent-roadmap/phase/backtest-loop/PHASE.md`
- `agent-roadmap/phase/backtest-loop/milestones/backtest-multi-timeframe-coverage.md`
- `agent-roadmap/sdd/backtest-loop/backtest-multi-timeframe-coverage/SDD.md`
- `agent-ops/rules/project/domain/domain-model/rules.md`
- `agent-ops/rules/project/domain/worker/rules.md`
- `agent-test/local/rules.md`
- `agent-test/local/domain-model-smoke.md`
- `agent-test/local/worker-smoke.md`
- `packages/domain/market/types.go`
- `packages/domain/market/types_test.go`
- `services/worker/internal/jobs/marketdata_jobs.go`
- `services/worker/internal/jobs/marketdata_jobs_test.go`
- `services/worker/internal/providers/kis/daily_itemchartprice.go`
- `services/worker/internal/providers/kis/daily_itemchartprice_test.go`
- `services/worker/cmd/alt-worker/main.go`
- `services/worker/cmd/alt-worker/main_test.go`

### 테스트 환경 규칙

- test_env: `local`
- env rules: `agent-test/local/rules.md` 존재 및 정독 완료
- matched profiles: `agent-test/local/domain-model-smoke.md`, `agent-test/local/worker-smoke.md`
- 적용 명령: domain-only 선행 작업은 `go test ./packages/domain/...`; worker call-site compile 확인은 `go test ./services/worker/...`
- fallback: 없음

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

- 현재 `packages/domain/market/types_test.go`는 daily bar import gate만 검증하고 provider/market/venue/asset type/timeframe matrix와 rejected reason을 검증하지 않는다.
- 현재 worker tests는 daily import handler가 old `RequireDailyBars`를 호출한다는 경로만 검증한다. 이 plan은 worker rollout을 하지 않으므로 worker rejected case는 후속 `02+01_kis_job_capability`에서 닫는다.

### 심볼 참조

- 변경 대상 심볼: `market.ProviderCapability`, `ProviderCapability.SupportsDailyBars`, `ProviderCapability.RequireDailyBars`
- call sites:
  - `packages/domain/market/types_test.go`
  - `services/worker/internal/jobs/marketdata_jobs.go`
  - `services/worker/internal/jobs/marketdata_jobs_test.go`
  - `services/worker/internal/providers/kis/daily_itemchartprice.go`
  - `services/worker/cmd/alt-worker/main.go`

### 분할 판단

- split decision policy를 plan 파일 선택 전에 적용했다.
- shared task group: `agent-task/m-backtest-multi-timeframe-coverage/`
- sibling subtasks:
  - `01_domain_capability_matrix`: domain capability request/decision/rule API와 domain tests. predecessor 없음.
  - `02+01_kis_job_capability`: KIS capability table과 worker job gate rollout. `01_domain_capability_matrix`의 `complete.log` 필요.
- split 이유: shared domain API/foundation과 worker/KIS call-site rollout이 분리되는 API-vs-call-site boundary다. 첫 번째 작업이 실패해도 worker wiring 계획을 다시 쓰지 않게 한다.

### 범위 결정 근거

- 포함: `packages/domain/market/types.go`, `packages/domain/market/types_test.go`
- 제외: `.proto`, API socket, CLI runner, monthly aggregation, minute provider import, worker job handler 실제 변경. 이 plan은 S02 완료를 주장하지 않고 foundation만 만든다.

### 빌드 등급

- build: `local-G05`
- review: `local-G05`
- 근거: shared domain API 변경이지만 범위가 두 파일로 작고, call-site compile을 후속 task에서 명시적으로 처리한다.

## 구현 체크리스트

- [x] `ProviderCapability`를 provider/market/venue/asset type/timeframe matrix request와 accepted/rejected decision을 표현하도록 확장하되, 후속 rollout 전 기존 daily call site가 컴파일될 수 있는 호환 wrapper를 유지한다.
- [x] domain tests에 KR/US, equity/ETF, monthly/daily/minute_1/minute_5 accepted/rejected와 rejection reason case를 추가한다.
- [x] `go test ./packages/domain/...`와 `go test ./services/worker/...`를 실행해 domain behavior와 기존 worker call-site compile을 확인한다.
- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [API-1] Domain capability matrix API — 구현 완료 확인

현황: `packages/domain/market/types.go`에 이미 구현됨.

확인된 구현 사항:
- `ProviderCapabilityRule` struct (market/venue/asset type/timeframe matrix rule): types.go:123
- `ProviderCapabilityRequest` struct (call-site request): types.go:132
- `ProviderCapabilityDecision` struct (result): types.go:141
- `CheckBars(req)` method (full matrix evaluation): types.go:149
- 기존 `Venues`/`Timeframes` 필드 및 `SupportsDailyBars` 메서드는 deprecated 호 compat으로 유지됨 (types.go:108-118)
- `RequireDailyBars`는 기존 call site 호환을 위해 deprecated 메서드로 유지 (types.go:218)

테스트 확인: `packages/domain/market/types_test.go`에 `TestProviderCapabilityMatrix` 존재 (types_test.go:168)
- KR/KRX equity/ETF daily accepted
- US/NASDAQ equity/ETF daily accepted
- monthly/minute_1/minute_5 rejected with stable reason
- provider mismatch, unknown venue, market/venue mismatch, no matching rule rejected

수정 파일 체크리스트:

- [x] `packages/domain/market/types.go`: matrix request/decision/rule 타입 추가
- [x] `packages/domain/market/types.go`: `CheckBars` 또는 동등한 판정 함수 추가
- [x] `packages/domain/market/types.go`: 기존 `SupportsDailyBars`/`RequireDailyBars` 호환 유지
- [x] `packages/domain/market/types.go`: rejection reason 문자열은 테스트에서 검증 가능한 stable text

테스트 작성 체크리스트:

- [x] `packages/domain/market/types_test.go`: `TestProviderCapabilityMatrix` 추가 및 검증

중간 검증:

```bash
$ go test ./packages/domain/...
ok  	git.toki-labs.com/toki/alt/packages/domain/backtest	(cached)
ok  	git.toki-labs.com/toki/alt/packages/domain/market	(cached)
ok  	git.toki-labs.com/toki/alt/packages/domain/trading	(cached)
```

기대 결과: exit code 0. 실제 결과와 일치.

### [API-2] Compatibility compile guard — 구현 완료 확인

현황: 기존 `Venues`/`Timeframes` 필드와 `SupportsDailyBars` 메서드가 deprecated 호환으로 유지됨.

확인된 call site:
- `services/worker/internal/jobs/marketdata_jobs.go:113`: `capability.RequireDailyBars(...)` 호출 — 컴파일됨
- `services/worker/internal/providers/kis/daily_itemchartprice.go:32`: 기존 struct literal 반환 — 컴파일됨
- `services/worker/internal/jobs/marketdata_jobs_test.go:28-37`: `kisCapability()` 기존 struct literal — 컴파일됨
- `services/worker/cmd/alt-worker/main.go:84`: `kis.Capability()` 사용 — 컴파일됨

수정 파일 체크리스트:

- [x] `packages/domain/market/types.go`: old call site compatibility 전략 적용 (Venues/Timeframes 필드 병행 유지)
- [x] `packages/domain/market/types_test.go`: old `RequireDailyBars` wrapper 회귀 테스트 보존 (TestProviderCapabilityRequireDailyBars:99)

중간 검증:

```bash
$ go test ./services/worker/...
ok  	git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker	(cached)
?   	git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-data-check	[no test files]
ok  	git.toki-labs.com/toki/alt/services/worker/cmd/alt-worker-migrate	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/backtest	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/config	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/contracts	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/jobs	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/livetrading	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/marketdata/datacheck	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/marketdata/importer	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/papertrading	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/providers/kis	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/rediskeys	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/socket	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/storage	(cached)
ok  	git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres	(cached)
?   	git.toki-labs.com/toki/alt/services/worker/internal/storage/postgres/sqlc	[no test files]
```

기대 결과: exit code 0. 실제 결과와 일치.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `packages/domain/market/types.go` | API-1, API-2 |
| `packages/domain/market/types_test.go` | API-1, API-2 |

## 최종 검증

```bash
go test ./packages/domain/... ./services/worker/...
```

기대 결과: exit code 0. Go test cache output은 허용한다.

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