<!-- task=m-backtest-data-collection-infrastructure/02+01_freshness_status plan=1 tag=REVIEW_CLI -->

# Plan - REVIEW_CLI Freshness Fixture Contract Repair

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

이 plan은 직전 `local-G06` 코드리뷰의 Required 이슈만 해결한다. 새 protobuf/API/worker/storage 변경은 범위 밖이다. 구현 후 `CODE_REVIEW-local-G07.md`의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운 뒤 active 파일을 그대로 두고 리뷰를 요청한다. 종결, log rename, `complete.log`, archive 이동은 code-review 전용이다.

구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 범위 충돌이 필요하면 `CODE_REVIEW-local-G07.md`의 `사용자 리뷰 요청` 섹션에 근거를 기록하고 멈춘다. 사용자에게 직접 질문하거나 선택지를 제시하거나 `request_user_input`을 호출하지 않는다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/backtest-loop/milestones/backtest-data-collection-infrastructure.md`
- Task ids:
  - `freshness-status`: 수집 성공, 실패, 누락, 최신 일자를 operator가 확인할 수 있는 상태 출력을 만든다.
- Completion mode: check-on-pass

## 배경

`collection_freshness` runner 구현과 기본 테스트는 들어갔지만, status handoff fixture가 "최신 일자"를 JSONL 계약으로 고정하지 못했다. 더 큰 문제는 `market_data_status_query`와 `us_market_data_status_query` expected JSONL에서 같은 scenario가 `list_bars count=10`을 보여주면서 freshness line은 동일 universe symbol을 missing으로 보고한다는 점이다. operator가 이 fixture를 기준으로 보면 수집된 bar가 있는데 freshness는 누락이라는 모순된 상태를 받는다.

## 범위 결정 근거

- 기존 `collection_freshness` action, API read orchestration, protobuf contract는 유지한다.
- fixture, handoff 문서, runner test fake response/expectation만 수정한다.
- 같은 Milestone Task의 완료 조건을 향하므로 `Roadmap Targets`를 유지한다.

## 구현 체크리스트

- [ ] `market_data_status_query`와 `us_market_data_status_query` freshness fixture 기대값과 runner fake instrument/bar data를 `freshness_status=fresh`, `missing_count=0`, `latest_yyyymmdd=<expected date>`로 맞춘다.
- [ ] Expected JSONL fixture와 `headless_validation.md`의 Expected output keys에 `latest_yyyymmdd`를 포함해 matrix-driven key test가 최신 일자 키를 검증하게 한다.
- [ ] 관련 tests가 text output과 JSONL/fixture 계약에서 freshness status, missing count, latest date를 의미 있게 확인하도록 보강한다.
- [ ] `go test ./apps/cli/internal/operator ./apps/cli/internal/cli`를 실행한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_CLI-1] Freshness Fixture Latest Contract

#### 문제

직전 리뷰에서 확인한 Required 이슈:

- `apps/cli/testdata/operator/expected/market_data_status_query.jsonl:5`
- `apps/cli/testdata/operator/expected/us_market_data_status_query.jsonl:5`
- `apps/cli/testdata/operator/headless_validation.md:33`
- `apps/cli/testdata/operator/headless_validation.md:34`

현재 expected JSONL은 `collection_freshness` line에 `latest_yyyymmdd`를 포함하지 않는다. 또한 status scenario의 `list_bars` line은 bar count를 보여주지만 freshness line은 같은 symbol을 `missing_symbols`로 기록한다.

#### 해결 방법

KR/US status scenario fixture는 수집된 bar가 있는 정상 상태의 handoff evidence로 정리한다.

Before:

```json
{"action":"collection_freshness","freshness_status":"missing","missing_count":1,"missing_symbols":["005930"],"scenario":"market_data_status_query","status":"ok","step":"freshness_status","type":"step","universe":"kr-core"}
```

After 예시:

```json
{"action":"collection_freshness","freshness_status":"fresh","latest_yyyymmdd":"20240501","missing_count":0,"scenario":"market_data_status_query","status":"ok","step":"freshness_status","type":"step","universe":"kr-core"}
```

구체 작업:

- `market_data_status_query.yaml`과 `us_market_data_status_query.yaml`의 freshness `expect`에 `freshness_status: fresh`, `missing_count: 0`, `latest_yyyymmdd`를 넣는다.
- `runner_market_test.go`의 status scenario fake `Instrument`에 `Symbol`을 채우고, `Bar.TimestampUnixMs`를 fixture expected date와 맞춘다.
- status scenario text assertions에 `freshness_status=fresh`, `missing_count=0`, `latest_yyyymmdd=...`를 추가한다.
- expected JSONL fixture의 freshness line을 fresh/latest로 갱신한다.
- `headless_validation.md`의 Expected output keys에 `latest_yyyymmdd`를 추가한다.
- 필요하면 hardcoded fallback `requiredScenarioKeys`도 같은 key를 포함하도록 갱신한다.

#### 테스트 결정

- 필수: `go test ./apps/cli/internal/operator ./apps/cli/internal/cli`
- 중간 검증: `go test ./apps/cli/internal/operator`

#### 중간 검증

```bash
go test ./apps/cli/internal/operator
```

기대 결과: exit code 0.

## 최종 검증

```bash
go test ./apps/cli/internal/operator ./apps/cli/internal/cli
```

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