<!-- task=m-us-market-expansion/01_market_foundation plan=1 tag=REVIEW_US_FOUNDATION -->

# Implementation Plan - REVIEW_US_FOUNDATION

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

구현 완료의 마지막 단계는 active `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 구현 내용, 결정, 검증 출력으로 채우는 것이다. 검증을 실행하고 실제 stdout/stderr를 붙이며, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 구현 중 사용자만 결정할 수 있는 범위 변경, 외부 환경/secret 준비, 또는 계획 충돌이 생기면 review stub의 `사용자 리뷰 요청` 섹션에 근거를 쓰고 멈춘다. 직접 사용자에게 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 후속 에이전트가 재실행으로 모을 수 있는 증거 공백은 사용자 리뷰 요청이 아니다. finalization, log rename, `complete.log`, archive 이동은 code-review 전용이다.

## 배경

이 리뷰는 `US_FOUNDATION` 1차 구현에서 production contract/storage round-trip과 검증 명령은 통과했지만, provider symbols fixture 테스트가 계획의 핵심 조건을 충분히 잠그지 못한 문제를 다룬다. 현재 fixture에는 `AAPL`/`SPY`, `USD`, `equity`/`etf`가 들어 있지만 테스트는 허용 enum 집합만 확인하므로 US/ETF row가 사라져도 통과할 수 있다. 이 follow-up은 fixture vocabulary 검증만 강화한다.

## 사용자 리뷰 요청 흐름

구현 중 차단은 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 템플릿은 `agent-ops/skills/common/_templates/implementation-user-review-request-section.md`와 동일하며, 구현 에이전트는 채팅으로 직접 질문하지 않는다. code-review가 해당 요청을 검증하고 실제 `USER_REVIEW.md` 작성 여부를 결정한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/trading-expansion/milestones/us-market-expansion.md`
- Task ids:
  - `us-instruments`: 미국장 instrument identity와 provider symbol mapping
  - `us-calendar`: 미국장 timezone/currency/venue 기준
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/private/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-test/local/rules.md`
- `agent-test/local/worker-smoke.md`
- `agent-ops/rules/project/domain/worker/rules.md`
- `agent-task/m-us-market-expansion/01_market_foundation/plan_cloud_G07_0.log`
- `agent-task/m-us-market-expansion/01_market_foundation/code_review_cloud_G07_0.log`
- `services/worker/internal/providers/kis/daily_itemchartprice_test.go`
- `services/worker/testdata/providers/kis/provider_symbols.sample.json`
- `packages/domain/market/types_test.go`

### 테스트 환경 규칙

`test_env=local`. `agent-test/local/rules.md`와 `agent-test/local/worker-smoke.md`를 읽었다. 적용 명령은 worker test 변경 기준 `go test -count=1 ./services/worker/internal/providers/kis`, 필요 시 `go test -count=1 ./services/worker/...`, milestone confidence용 `bin/test`, whitespace 확인용 `git diff --check`다. 이 follow-up은 `.proto`, generated output, sqlc output을 바꾸지 않는다.

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

- `TestProviderSymbolsFixtureVocabulary`는 venue/currency/asset_type이 허용 목록에 속하는지만 확인한다. `AAPL`/`SPY` US watchlist coverage, `NASDAQ`/`USD`, `equity`와 `etf`의 동시 존재, KIS provider symbol mapping을 필수 row 단위로 검증하지 않는다.

### 심볼 참조

Renamed/removed symbol: none.

### 분할 판단

기존 split task `m-us-market-expansion/01_market_foundation` 안의 리뷰 follow-up이다. 변경 범위가 단일 worker fixture test와 관련 JSON fixture 검증에 한정되어 새 subtask split은 만들지 않는다. sibling `02+01_kis_us_daily_bars`, `03+01_shared_query_surface`, `04+02,03_us_backtest_smoke`의 active state는 건드리지 않는다.

### 범위 결정 근거

Production `AssetType` domain/contract/storage/socket mapping, migration, generated contract output은 1차 구현과 재검증에서 통과했으므로 이 follow-up 범위에서 제외한다. fixture 내용 자체는 이미 목표 데이터를 담고 있으므로, 테스트를 강화하다가 fixture 불일치가 드러난 경우에만 `provider_symbols.sample.json`을 최소 수정한다. KIS live import, CLI query surface, backtest smoke, roadmap 문서는 제외한다.

### 빌드 등급

`local-G06`: repo 안에서 결정적으로 재현 가능한 test coverage follow-up이고 변경 파일이 bounded worker test/fixture에 한정된다.

## 구현 체크리스트

- [ ] [REVIEW_US_FOUNDATION-1] KIS provider symbols fixture test가 US watchlist와 `NASDAQ`/`USD`/`equity`/`etf`/KIS provider symbol mapping을 필수 row 단위로 검증하도록 강화한다. 검증: `AAPL`/`SPY` 또는 ETF row가 제거되면 테스트가 실패해야 한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_US_FOUNDATION-1] Strengthen US Fixture Vocabulary Assertions

문제: [services/worker/internal/providers/kis/daily_itemchartprice_test.go](/config/workspace/alt/services/worker/internal/providers/kis/daily_itemchartprice_test.go:258)의 `TestProviderSymbolsFixtureVocabulary`는 fixture instrument가 허용 venue/currency/asset_type 중 하나인지 확인하지만, [services/worker/testdata/providers/kis/provider_symbols.sample.json](/config/workspace/alt/services/worker/testdata/providers/kis/provider_symbols.sample.json:45)의 US rows가 실제로 존재해야 한다는 조건은 확인하지 않는다.

해결 방법:

```go
// Before services/worker/internal/providers/kis/daily_itemchartprice_test.go:258
for i, inst := range fx.Instruments {
    v := market.Venue(inst.Venue)
    if v != market.VenueKRX && v != market.VenueNASDAQ && v != market.VenueNYSE {
        t.Errorf("instrument[%d] unexpected venue: %q", i, inst.Venue)
    }
    c := market.Currency(inst.Currency)
    if c != market.CurrencyKRW && c != market.CurrencyUSD {
        t.Errorf("instrument[%d] unexpected currency: %q", i, inst.Currency)
    }
    at := market.AssetType(inst.AssetType)
    if at != market.AssetTypeEquity && at != market.AssetTypeETF {
        t.Errorf("instrument[%d] unexpected asset type: %q", i, inst.AssetType)
    }
}
```

```go
// After
required := map[string]struct {
    market    market.Market
    venue     market.Venue
    symbol    string
    currency  market.Currency
    assetType market.AssetType
}{
    "NASDAQ:AAPL": {market.MarketUS, market.VenueNASDAQ, "AAPL", market.CurrencyUSD, market.AssetTypeEquity},
    "NASDAQ:SPY":  {market.MarketUS, market.VenueNASDAQ, "SPY", market.CurrencyUSD, market.AssetTypeETF},
}
```

수정 파일 및 체크리스트:

- [ ] `services/worker/internal/providers/kis/daily_itemchartprice_test.go`: fixture instruments를 id map으로 만들고 `NASDAQ:AAPL`, `NASDAQ:SPY`의 market/venue/symbol/currency/asset_type/provider symbol 값을 정확히 assert한다.
- [ ] `services/worker/internal/providers/kis/daily_itemchartprice_test.go`: watchlist selector가 `AAPL`과 `SPY`를 포함하는지 assert한다.
- [ ] `services/worker/testdata/providers/kis/provider_symbols.sample.json`: 강화된 assertion과 fixture가 불일치할 때만 최소 수정한다.

테스트 작성: 작성한다. `TestProviderSymbolsFixtureVocabulary`에 exact US fixture expectations와 watchlist symbol coverage assertion을 추가한다.

중간 검증:

```bash
go test -count=1 ./services/worker/internal/providers/kis
```

## 수정 파일 요약

| 파일 | 항목 |
|---|---|
| `services/worker/internal/providers/kis/daily_itemchartprice_test.go` | REVIEW_US_FOUNDATION-1 |
| `services/worker/testdata/providers/kis/provider_symbols.sample.json` | REVIEW_US_FOUNDATION-1 |

## 최종 검증

```bash
go test -count=1 ./services/worker/internal/providers/kis
go test -count=1 ./services/worker/...
bin/test
git diff --check
```

`go test` cache는 허용하지 않는다. `bin/test`는 workspace confidence 확인이며 일부 Go package가 cache를 출력해도, 앞선 `-count=1` worker 검증이 이 follow-up의 fresh 검증이다.

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