<!-- task=m-backtest-multi-timeframe-coverage/03_monthly_aggregation plan=1 tag=REVIEW_REFACTOR -->

# Plan - Monthly Aggregation Review Follow-up

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

구현 마지막 단계는 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 변경 내용과 검증 출력으로 채우는 것이다. 구현 후 active 파일을 그대로 두고 리뷰 준비를 보고한다. 종결, archive 이동, `complete.log` 작성은 code-review 전용이다.

선택된 SDD 결정 또는 Milestone `구현 잠금 > 결정 필요` 항목이 실구현을 막을 때만 review stub의 `사용자 리뷰 요청` 섹션을 채우고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다. 환경/secret/서비스 차단, 일반 범위 조정, 검증 공백은 사용자 리뷰 요청이 아니라 `검증 결과` 또는 `계획 대비 변경 사항`에 기록한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/backtest-loop/milestones/backtest-multi-timeframe-coverage.md`
- Task ids:
  - `monthly-bars`: 월봉을 일봉 aggregation으로 생성하고, 생성 기준과 provenance를 저장/출력한다.
- Completion mode: check-on-pass

## Spec Targets

- SDD: `agent-roadmap/sdd/backtest-loop/backtest-multi-timeframe-coverage/SDD.md`
- Acceptance scenarios:
  - `S04`: task=`monthly-bars`; evidence=`deterministic monthly OHLCV fixture와 provenance evidence`
- Completion mode: spec-check-on-pass

## Archive Evidence Snapshot

- Archived plan: `agent-task/m-backtest-multi-timeframe-coverage/03_monthly_aggregation/plan_local_G05_0.log`
- Archived review: `agent-task/m-backtest-multi-timeframe-coverage/03_monthly_aggregation/code_review_local_G05_0.log`
- Verdict: FAIL
- Required summary:
  - `services/worker/internal/marketdata/aggregation/monthly.go:185`: provenance가 각 monthly bar의 해당 월 source range/count가 아니라 전체 입력 source range/count를 반복한다.
  - `services/worker/internal/marketdata/aggregation/monthly_test.go:335`: fixture comparison이 OHLCV/currency/provenance를 비교하지 않고, `monthly_expected.json`도 provenance fixture를 포함하지 않는다.
- Affected files:
  - `services/worker/internal/marketdata/aggregation/monthly.go`
  - `services/worker/internal/marketdata/aggregation/monthly_test.go`
  - `services/worker/internal/marketdata/aggregation/testdata/monthly_daily_input.json`
  - `services/worker/internal/marketdata/aggregation/testdata/monthly_expected.json`
- Verification evidence:
  - Review rerun `go test ./services/worker/internal/marketdata/...`: exit code 0, but current tests do not prove SDD S04 fixture evidence.
  - Review rerun `go test ./services/worker/...`: exit code 0.
  - Review rerun `git diff --check`: exit code 0.
- Narrow archive reread allowed if exact prior context is needed:
  - `agent-task/m-backtest-multi-timeframe-coverage/03_monthly_aggregation/plan_local_G05_0.log`
  - `agent-task/m-backtest-multi-timeframe-coverage/03_monthly_aggregation/code_review_local_G05_0.log`
- Roadmap/spec carryover:
  - Roadmap task `monthly-bars`.
  - Spec scenario `S04`.

## 범위 결정 근거

- 같은 Milestone task와 SDD S04 evidence를 닫기 위한 follow-up이다. Roadmap Targets와 Spec Targets는 유지한다.
- DB migration, provider 월봉 import, backtest selector integration은 여전히 제외한다.
- 현재 review file의 구현 설명은 UTC 기준 grouping을 선택했다고 기록했다. 이 follow-up은 기본적으로 그 선택을 유지하고 fixture expected를 그 규칙과 일치시킨다. 만약 구현 중 market wall-clock grouping으로 바꾸는 것이 맞다고 판단하면 `계획 대비 변경 사항`에 plan deviation과 근거를 남기고, 모든 fixture/test 기대값을 그 결정과 일치시킨다.

## 구현 체크리스트

- [ ] `AggregateDailyToMonthly` provenance를 월별 bucket source range/count 기준으로 수정한다.
- [ ] `monthly_expected.json`을 deterministic monthly OHLCV와 provenance evidence를 모두 포함하는 stable fixture로 갱신한다.
- [ ] fixture comparison test가 OHLCV, currency, timestamp, provenance source range/count, rule id를 모두 검증하게 수정한다.
- [ ] `go test ./services/worker/internal/marketdata/aggregation -count=1`, `go test ./services/worker/internal/marketdata/...`, `go test ./services/worker/...`, `git diff --check`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_REFACTOR-1] Per-Month Provenance Correction

#### 문제

현재 `AggregateDailyToMonthly`는 월별 result bar를 만든 뒤 전체 입력의 `sourceStart`, `sourceEnd`, `len(validatedBars)`를 모든 provenance에 넣는다. 이러면 January monthly bar도 February daily source를 provenance로 가리킬 수 있어 SDD S04의 source range evidence가 틀린다.

#### 해결 방법

월별 aggregation bucket에 `sourceStart`, `sourceEnd`, `sourceCount`를 함께 유지한다. 각 월에 bar를 추가할 때 해당 bucket의 source range/count만 갱신하고, result 생성 시 같은 월의 provenance를 만든다. `AggregationRuleID`는 기존 `monthly-deterministic-v1`을 유지하거나 상수로 승격한다.

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

- [ ] `services/worker/internal/marketdata/aggregation/monthly.go`: 월별 source range/count를 bucket 단위로 기록한다.
- [ ] `services/worker/internal/marketdata/aggregation/monthly_test.go`: 각 monthly bar provenance가 해당 월 daily input만 가리키는지 검증한다.

#### 테스트 결정

기존 deterministic OHLCV test에 provenance range/count assertion을 구체화하거나 별도 test를 추가한다. 최소한 두 개 이상의 월이 있는 input에서 각 월의 provenance count와 start/end가 서로 다르다는 것을 검증한다.

#### 중간 검증

```bash
go test ./services/worker/internal/marketdata/aggregation -count=1
```

### [REVIEW_REFACTOR-2] Fixture Evidence Restoration

#### 문제

`monthly_expected.json`은 bare bar array만 포함하고 provenance fixture가 없다. `TestAggregateDailyToMonthlyFixtureComparison`도 expected fixture에서 instrument/timeframe/timestamp만 확인하므로, OHLCV와 provenance가 틀려도 SDD S04 evidence가 통과할 수 있다.

#### 해결 방법

expected fixture를 `bars`와 `provenance`를 모두 담는 stable 구조로 갱신한다. test는 fixture를 typed struct로 decode하고, actual result를 같은 fixture shape으로 변환해 deep comparison 또는 field-by-field comparison을 수행한다. 현재 input fixture의 `+09:00` timestamp를 유지한다면 UTC 기준 grouping 결과가 expected OHLCV/provenance에 반영되어야 한다. UTC boundary 혼선을 피하려고 fixture를 UTC timestamp로 바꾸는 경우에는 그 선택을 `계획 대비 변경 사항`에 명시한다.

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

- [ ] `services/worker/internal/marketdata/aggregation/testdata/monthly_expected.json`: `bars`와 `provenance`를 모두 포함한다.
- [ ] `services/worker/internal/marketdata/aggregation/monthly_test.go`: fixture comparison이 OHLCV, currency, timestamp, provenance source range/count, rule id를 모두 비교한다.
- [ ] `services/worker/internal/marketdata/aggregation/testdata/monthly_daily_input.json`: timestamp convention이 expected fixture와 일치하는지 확인하고 필요 시 갱신한다.

#### 테스트 결정

fixture comparison은 SDD S04 evidence의 핵심 검증이다. 이 test가 실패하면 `monthly-bars` task와 `S04`는 완료로 볼 수 없다.

#### 중간 검증

```bash
go test ./services/worker/internal/marketdata/aggregation -count=1
```

## 최종 검증

```bash
go test ./services/worker/internal/marketdata/aggregation -count=1
go test ./services/worker/internal/marketdata/...
go test ./services/worker/...
git diff --check
```

기대 결과: 모든 명령 exit code 0. `TestAggregateDailyToMonthlyFixtureComparison`은 expected fixture의 OHLCV와 provenance까지 실제로 비교해야 한다.
