alt/agent-task/m-scheduled-market-data-refresh/02_retry_backfill/PLAN-local-G04.md

8.3 KiB

Plan - BACKFILL

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

CODE_REVIEW-local-G04.md의 구현 에이전트 소유 섹션을 채우는 것이 구현의 마지막 단계다. 검증 명령을 실행하고 실제 stdout/stderr를 붙여 넣은 뒤 active 파일을 그대로 두고 review ready 상태로 보고한다. 선택된 SDD 결정이나 선택된 Milestone 구현 잠금 > 결정 필요 항목이 막으면 직접 질문하지 말고 review stub의 사용자 리뷰 요청 섹션에 근거를 기록한다. 구현 에이전트는 USER_REVIEW.md, complete.log, archive 로그를 만들지 않는다.

배경

retry-backfill은 provider delay, missing, gap을 성공으로 숨기지 않고 stale/error 상태와 backfill window로 남겨야 한다. 현 코드에는 schedule config validation은 있지만 freshness result를 retry/backfill decision으로 바꾸는 worker-local 계산 표면이 없다. SDD S03은 fixture 또는 local smoke에서 missing/gap/provider delay 케이스가 stable text/JSONL로 구분되는 증거를 요구한다.

사용자 리뷰 요청 흐름

사용자 리뷰는 선택된 SDD decision 또는 Milestone lock decision만 active review stub의 사용자 리뷰 요청 섹션에 기록한다. 구현 중 직접 채팅 질문, 선택지 제시, request_user_input 호출은 금지한다. code-review가 요청 타당성을 검증하고 실제 USER_REVIEW.md 작성 여부를 결정한다.

Roadmap Targets

  • Milestone: agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md
  • Task ids:
    • retry-backfill: provider 지연, 결측, gap 결과에 따라 retry와 backfill window를 계산하고 실패를 stale/error 상태로 남긴다.
  • Completion mode: check-on-pass

Spec Targets

  • SDD: agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md
  • Acceptance scenarios:
    • S03: task=retry-backfill; evidence=missing/gap/provider delay fixture 또는 local smoke
  • Completion mode: spec-check-on-pass

분석 결과

읽은 파일

  • agent-test/local/rules.md
  • agent-test/local/worker-smoke.md
  • agent-roadmap/phase/backtest-loop/milestones/scheduled-market-data-refresh.md
  • agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md
  • services/worker/internal/scheduler/config.go
  • services/worker/internal/scheduler/config_test.go
  • services/worker/internal/jobs/marketdata_jobs.go
  • services/worker/internal/marketdata/importer/importer.go
  • services/worker/internal/storage/postgres/queries/queries.sql
  • services/worker/go.mod

테스트 환경 규칙

test_env는 local이다. agent-test/local/rules.mdagent-test/local/worker-smoke.md를 읽었다. services/worker/** 변경이므로 focused command는 go test -count=1 ./services/worker/internal/scheduler, 전체 worker smoke는 go test ./services/worker/...다. storage SQL을 바꾸지 않으므로 bin/worker-storage-check는 필수 검증이 아니다.

테스트 커버리지 공백

  • schedule validation output은 현재 커버된다.
  • missing/gap/provider_delay를 backfill decision으로 바꾸는 worker-local tests가 없다.
  • stale/error text/JSONL output fixture가 없다.

심볼 참조

none. symbol rename/remove 없음.

분할 판단

split decision policy를 먼저 평가했다. shared task group은 m-scheduled-market-data-refresh다. 이 subtask는 02_retry_backfill이고 depends_on=[]이다. scheduled-runner와 독립적으로 pure calculator와 stable output을 만들 수 있어 predecessor complete.log를 요구하지 않는다.

범위 결정 근거

이 plan은 retry/backfill calculation과 stable evidence output만 다룬다. worker long-running loop, API/contracts schema, status CLI, remote runner smoke, backtest-readiness는 제외한다. provider live 호출과 secret 값은 다루지 않는다.

빌드 등급

local-G04. 새 계산 표면과 fixture tests가 필요하지만 worker 내부 pure logic이며 외부 runtime 없이 검증 가능하다.

구현 체크리스트

  • services/worker/internal/scheduler에 freshness observation -> retry/backfill decision 계산 타입과 함수를 추가한다.
  • missing/gap/provider_delay/error 케이스를 stable text/JSONL로 출력하는 writer와 fixture-style unit tests를 추가한다.
  • retry-backfill 검증: fixture 또는 local smoke에서 missing/gap/provider delay 케이스가 stable text/JSONL로 구분된다.
  • 최종 검증으로 go test -count=1 ./services/worker/internal/schedulergo test ./services/worker/...를 실행한다.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

[BACKFILL-1] Retry/Backfill Decision Calculator

문제: SDD는 provider delay나 gap을 성공으로 숨기지 말라고 고정한다(agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md:75). 현재 scheduler package는 validation item만 정의하고(services/worker/internal/scheduler/config.go:74) freshness observation이나 backfill decision type이 없다.

Before:

// services/worker/internal/scheduler/config.go:74
// ValidationItem is a stable text/JSONL evidence row.
type ValidationItem struct {

해결 방법: services/worker/internal/scheduler/backfill.go를 추가한다. FreshnessObservation은 schedule, provider, selector, timeframe, expected_from/to, latest, missing dates, gap buckets, duplicate count, provider_delay_days, error를 담는다. DecideBackfill(observation, window)는 success/fresh, stale/missing, stale/gap, stale/provider_delay, error를 분리하고 earliest missing/gap/latest 기준으로 inclusive backfill_from/backfill_to를 계산한다.

수정 파일 및 체크리스트:

  • services/worker/internal/scheduler/backfill.go: FreshnessObservation, BackfillDecision, DecideBackfill.
  • services/worker/internal/scheduler/backfill_test.go: missing, gap, provider delay, duplicate-only, error 케이스.

테스트 작성: TestDecideBackfillDistinguishesMissingGapProviderDelayTestDecideBackfillPreservesErrorState를 추가한다.

중간 검증:

go test -count=1 ./services/worker/internal/scheduler

기대 결과: exit code 0. backfill calculator tests pass.

[BACKFILL-2] Stable Text/JSONL Evidence

문제: SDD S03은 stale/error 상태와 backfill window가 stable text/JSONL로 구분되어야 한다(agent-roadmap/sdd/backtest-loop/scheduled-market-data-refresh/SDD.md:87). 현재 scheduler output은 config validation용 WriteText/WriteJSONL뿐이고(services/worker/internal/scheduler/config.go:272), retry/backfill decision writer가 없다.

Before:

// services/worker/internal/scheduler/config.go:272
// WriteText renders stable operator-facing dry-run lines.
func WriteText(w io.Writer, validation Validation) error {

해결 방법: WriteBackfillTextWriteBackfillJSONL을 추가한다. text는 schedule=<name> status=<fresh|stale|error> reason=<...> backfill_from=<YYYYMMDD> backfill_to=<YYYYMMDD> retry=<true|false> 형태로, JSONL은 같은 필드를 stable struct tag로 출력한다. tests는 expected substrings와 JSONL fields를 모두 고정한다.

수정 파일 및 체크리스트:

  • services/worker/internal/scheduler/backfill.go: writer 함수와 JSON field tags.
  • services/worker/internal/scheduler/backfill_test.go: text/JSONL expected output tests.

테스트 작성: TestWriteBackfillTextAndJSONL를 추가한다.

중간 검증:

go test -count=1 ./services/worker/internal/scheduler

기대 결과: exit code 0. stable output tests pass.

수정 파일 요약

파일 항목
services/worker/internal/scheduler/backfill.go BACKFILL-1, BACKFILL-2
services/worker/internal/scheduler/backfill_test.go BACKFILL-1, BACKFILL-2

최종 검증

go test -count=1 ./services/worker/internal/scheduler
go test ./services/worker/...

Go test cache output is acceptable only for the broad second command; the focused first command must use -count=1.

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