<!-- task=m-scheduled-market-data-refresh/04+03_refresh_status_cli plan=0 tag=cloud-G08 -->

# Plan - Refresh Status API and CLI

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

이 plan은 `Scheduled Market Data Refresh` milestone handoff 에픽의 `refresh-status` roadmap target을 완료하기 위한 통합 작업이다. 선행 `03+01,02_refresh_status_model`이 완료되어 `complete.log`가 생긴 뒤에만 시작한다.

## 배경

SDD S04는 scheduler tick 후 operator가 refresh 상태를 success/stale/error로 확인하고, `last_success`, `last_error`, `next_run`, imported bar count, missing/gap/duplicate/provider_delay를 evidence로 남기는 것을 요구한다. 현재 operator CLI에는 market data freshness/status query fixture가 있지만 scheduler refresh status action과 field set은 없다.

## 사용자 리뷰 요청 흐름

protobuf message 이름, action 이름, JSONL 필드명, status 의미 중 기존 SDD와 충돌하거나 구현 중 두 가지 이상 후보가 동등하게 보이면 작업을 멈추고 USER_REVIEW를 요청한다. remote 환경 endpoint, credential, provider 선택은 코드에 하드코딩하지 않는다.

## Archive Evidence Snapshot

- `agent-task/archive/2026/06/m-scheduled-market-data-refresh/01_scheduled_runner/complete.log`: S02 완료 PASS.
- `agent-task/archive/2026/06/m-scheduled-market-data-refresh/02_retry_backfill/complete.log`: S03 완료 PASS.
- 선행 active task 필요: `agent-task/m-scheduled-market-data-refresh/03+01,02_refresh_status_model/complete.log`가 아직 없다. 구현 시작 전 반드시 확인한다.

## Roadmap Targets

- `agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md`
  - Handoff epic: `[refresh-status] success/stale/error status`

## 분석 결과

### 읽은 파일

- `agent-roadmap/current.md`
- `agent-roadmap/phase/backtest-loop/PHASE.md`
- `agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md`
- `agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md`
- `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/plan/SKILL.md`
- `agent-test/local/rules.md`
- `agent-test/local/profiles/worker-smoke.md`
- `agent-test/local/profiles/operations-smoke.md`
- `agent-test/local/profiles/contracts-smoke.md`
- `agent-test/local/profiles/api-smoke.md`
- `agent-ops/rules/domain/worker/rules.md`
- `agent-ops/rules/domain/operations/rules.md`
- `agent-ops/rules/domain/contracts/rules.md`
- `agent-ops/rules/domain/api/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/worker/internal/contracts/parser_map.go`
- `services/api/internal/socket/market.go`
- `services/worker/internal/socket/market.go`
- `services/worker/internal/scheduler/backfill.go`
- `services/worker/internal/scheduler/config.go`
- `services/worker/internal/scheduler/runner.go`
- `services/worker/cmd/alt-worker/main.go`
- `apps/cli/internal/operator/scenario.go`
- `apps/cli/internal/operator/output.go`
- `apps/cli/internal/operator/runner.go`
- `apps/cli/internal/operator/handoff_test.go`
- `apps/cli/internal/operator/runner_market_test.go`
- `apps/cli/testdata/operator/headless_validation.md`
- `apps/cli/testdata/operator/market_data_status_query.yaml`
- `apps/cli/testdata/operator/expected/market_data_status_query.jsonl`

### SDD 기준

- S04: remote runner에서 scheduler tick 이후 success/stale/error refresh 상태를 확인한다.
- Required fields: `last_success`, `last_error`, `next_run`, imported bar count, missing/gap/duplicate/provider_delay.
- Evidence Map S04: `Refresh status JSONL + operator CLI transcript`.

### 테스트 환경 규칙

- 테스트 환경: local.
- 적용 profile: `worker-smoke`, `api-smoke`, `contracts-smoke`, `operations-smoke`.
- remote runner evidence가 필요한 경우 endpoint/credential은 환경 변수나 기존 runner 설정을 사용하고 repository에 기록하지 않는다.

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

- operator scenario action에 scheduler refresh status query가 없다.
- protobuf contract에 refresh status 요청/응답 message가 없다.
- worker scheduler status가 worker socket/API를 통해 조회되지 않는다.
- existing `market_data_status_query` fixture는 provider/import/freshness/gap 위주이며 S04 필수 field set을 보장하지 않는다.

### 심볼 참조

- 기존 market/backtest action 이름과 response message는 rename하지 않는다.
- 새 action은 기존 `ActionCollectionFreshness`, `ActionMarketStatus` 흐름과 충돌하지 않는 이름을 사용한다.

### 분할 판단

- 이 task group은 `m-scheduled-market-data-refresh`다.
- archive 선행 `01_scheduled_runner`, `02_retry_backfill`은 완료됐다.
- active 선행 `03+01,02_refresh_status_model`은 아직 완료되지 않았다. 구현 시작 전 `complete.log`를 확인한다.
- 이 plan이 완료되면 roadmap target `refresh-status`를 체크할 수 있다.
- 후속 `05+04_backtest_readiness`는 이 plan의 완료 뒤 시작한다.

### 범위 결정 근거

S04 완료에는 contract, generated code, API socket, worker socket, operator CLI fixture/evidence가 모두 필요하다. 이는 small task가 아니므로 별도 G08 통합 plan으로 둔다.

### 빌드 등급

`cloud-G08`. contract/API/worker/operator CLI를 모두 건드리고 remote evidence까지 요구될 수 있는 cross-domain 작업이다.

## 의존 관계 및 구현 순서

1. `agent-task/m-scheduled-market-data-refresh/03+01,02_refresh_status_model/complete.log` 존재와 PASS 결과를 확인한다.
2. protobuf contract를 additive로 확장하고 generated code를 갱신한다.
3. worker scheduler status store/query를 worker socket에 연결한다.
4. API market socket forwarding을 추가한다.
5. operator scenario action, output field, fixture, expected JSONL, handoff matrix를 갱신한다.
6. local smoke와 필요 remote evidence를 실행하고 `refresh-status` roadmap target을 체크한다.

## 구현 체크리스트

### [API-1] Refresh status protobuf contract 추가

- 문제: API/worker/operator가 공유할 typed refresh status 계약이 없다.
- 해결: `packages/contracts/proto/alt/v1/market.proto`에 additive request/response/message를 추가하고 generated code를 갱신한다.
- 파일 체크리스트:
  - `packages/contracts/proto/alt/v1/market.proto`
  - generated protobuf outputs
  - `services/api/internal/contracts/parser_map.go`
  - `services/worker/internal/contracts/parser_map.go`
- 구현 기준:
  - 요청은 전체 schedule 또는 특정 schedule 조회를 지원한다.
  - 응답은 repeated status와 `ErrorInfo` 패턴을 기존 market contract와 맞춘다.
  - 필수 field: schedule/name, status, `last_success`, `last_error`, `next_run`, imported bar count, missing/gap/duplicate/provider_delay.
  - timestamp 표현은 기존 generated contract 관례와 맞춘다.
- 테스트 결정:
  - parser map 또는 contract decode 경로 테스트를 추가/갱신한다.
- 중간 검증:
  - `bin/contracts-gen`
  - `bin/contracts-check`

### [API-2] Worker socket refresh status 조회 연결

- 문제: scheduler tick 상태가 worker socket으로 조회되지 않는다.
- 해결: 선행 model을 worker runtime status store와 연결하고 worker market socket handler에서 contract response를 반환한다.
- 파일 체크리스트:
  - `services/worker/internal/scheduler/*.go`
  - `services/worker/internal/socket/market.go`
  - `services/worker/cmd/alt-worker/main.go`
  - worker socket tests
- 구현 기준:
  - scheduler tick 성공/실패 시 `last_success`, `last_error`, imported bar count를 보존한다.
  - validation schedule에서 `next_run`을 계산해 status에 포함한다.
  - stale/error/missing/gap/duplicate/provider_delay는 선행 model의 의미를 유지한다.
  - scheduler가 비활성화된 경우 typed unavailable/error response를 반환한다.
- 테스트 결정:
  - success/stale/error worker socket 조회 테스트를 추가한다.
- 중간 검증:
  - `go test -count=1 ./services/worker/internal/scheduler ./services/worker/internal/socket`

### [API-3] API market socket forwarding 추가

- 문제: operator는 API endpoint를 통해 worker refresh status를 조회해야 한다.
- 해결: API market socket handler가 새 request를 worker client로 forwarding하고 response를 그대로 contract에 맞게 반환한다.
- 파일 체크리스트:
  - `services/api/internal/socket/market.go`
  - API socket/client 관련 tests
- 구현 기준:
  - 기존 market data status/freshness handler의 error propagation 패턴을 따른다.
  - worker unavailable, invalid schedule, empty status를 구분 가능한 response로 둔다.
- 테스트 결정:
  - API handler forwarding 및 error propagation 테스트를 추가한다.
- 중간 검증:
  - `go test -count=1 ./services/api/internal/socket`

### [API-4] Operator refresh status scenario action 추가

- 문제: S04 evidence를 생성할 operator action과 JSONL field가 없다.
- 해결: operator scenario에 refresh status action을 추가하고 output/expect/fixture/handoff matrix를 갱신한다.
- 파일 체크리스트:
  - `apps/cli/internal/operator/scenario.go`
  - `apps/cli/internal/operator/output.go`
  - `apps/cli/internal/operator/runner.go`
  - `apps/cli/internal/operator/runner_market_test.go`
  - `apps/cli/internal/operator/handoff_test.go`
  - `apps/cli/testdata/operator/headless_validation.md`
  - `apps/cli/testdata/operator/*refresh_status*.yaml`
  - `apps/cli/testdata/operator/expected/*refresh_status*.jsonl`
- 구현 기준:
  - action 이름은 명확하게 scheduler refresh status임을 드러낸다.
  - JSONL에는 S04 필수 필드가 모두 나타난다.
  - success/stale/error fixture 또는 table-driven test를 통해 status별 field를 검증한다.
  - 기존 `market_data_status_query` fixture를 억지로 확장하기보다 scheduler refresh status fixture를 분리한다.
- 테스트 결정:
  - fixture expected output exact-match 테스트를 추가한다.
  - handoff matrix가 새 scenario를 참조하도록 갱신한다.
- 중간 검증:
  - `go test -count=1 ./apps/cli/internal/operator -run 'Test(RunScenarioRefreshStatus|HeadlessValidationHandoff|ExpectedOutputFixtures)'`

### [TEST-1] Cross-domain smoke 검증

- 문제: contract/API/worker/operator 변경은 domain별 단위 테스트만으로 regression을 놓칠 수 있다.
- 해결: local smoke profile을 순서대로 실행하고 결과를 review 파일에 기록한다.
- 파일 체크리스트:
  - `CODE_REVIEW_cloud_G08.md`
- 테스트 결정:
  - contracts, worker, API, operations smoke를 모두 수행한다.
- 중간 검증:
  - `go test ./packages/contracts/gen/go/...`
  - `go test ./services/api/...`
  - `go test ./services/worker/...`
  - `go test ./apps/cli/internal/operator -run 'Test(RunScenarioRefreshStatus|HeadlessValidationHandoff|ExpectedOutputFixtures)'`

### [TEST-2] Roadmap target 반영

- 문제: S04 evidence 없이 roadmap target을 체크하면 milestone 상태가 부정확해진다.
- 해결: local/remote evidence PASS 후 milestone handoff epic의 `[refresh-status]`만 체크한다.
- 파일 체크리스트:
  - `agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md`
  - `CODE_REVIEW_cloud_G08.md`
- 테스트 결정:
  - remote runner가 필요한 경우 실행 transcript 위치와 PASS 기준을 review 파일에 기록한다.
- 중간 검증:
  - `git diff -- agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md`

- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## 수정 파일 요약

- `packages/contracts/proto/alt/v1/market.proto` 및 generated files: refresh status contract 추가.
- `services/worker/internal/...`: scheduler status store/query와 worker socket response 추가.
- `services/api/internal/...`: API forwarding 추가.
- `apps/cli/internal/operator/...`: scenario action, output, tests 추가.
- `apps/cli/testdata/operator/...`: refresh status fixture/evidence와 handoff matrix 갱신.
- `agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md`: PASS 후 `[refresh-status]` 체크.
- `CODE_REVIEW_cloud_G08.md`: 구현 요약, 검증 로그, evidence 위치 기록.

## 최종 검증

- `bin/contracts-check`
- `go test ./packages/contracts/gen/go/...`
- `go test ./services/api/...`
- `go test ./services/worker/...`
- `go test ./apps/cli/internal/operator -run 'Test(RunScenarioRefreshStatus|HeadlessValidationHandoff|ExpectedOutputFixtures)'`
- 필요 시 remote runner refresh-status scenario 실행 및 transcript 기록

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