alt/agent-task/m-backtest-multi-timeframe-coverage/01_domain_capability_matrix/PLAN-local-G05.md
toki 97373ca14e feat(agent-task): m-backtest-multi-timeframe-coverage 작업 계획과 코드 리뷰를 추가한다
01_domain_capability_matrix: PLAN-local-G05, CODE_REVIEW-local-G05
02+01_kis_job_capability: PLAN-local-G06, CODE_REVIEW-local-G06
2026-06-17 21:37:12 +09:00

10 KiB

Plan - API

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

CODE_REVIEW-local-G05.md의 구현 에이전트 소유 섹션을 채우는 것이 구현의 마지막 단계다. 코드를 바꾸고 검증을 실행한 뒤 실제 구현 내용과 stdout/stderr를 리뷰 stub에 남기고, active 파일은 그대로 둔 채 리뷰 준비를 보고한다. 선택된 SDD 결정 또는 Milestone 구현 잠금 > 결정 필요 항목이 막으면 리뷰 stub의 사용자 리뷰 요청만 채우고 멈춘다. 구현 중 사용자에게 직접 질문하거나 선택지를 제시하거나 request_user_input, USER_REVIEW.md 작성, log archive, complete.log 작성을 하지 않는다. 환경/secret/service 차단과 검증 증거 공백은 사용자 리뷰가 아니라 검증 결과 또는 후속 plan 대상으로 남긴다.

배경

capability-matrix는 provider, market, venue, asset type, timeframe 조합별 accepted/rejected와 거부 사유를 표현해야 한다. 현재 ProviderCapability는 venue/timeframe map과 daily 전용 RequireDailyBars만 있어 monthly/minute rejected case와 asset type 차원을 표현할 수 없다. 이 선행 plan은 domain 모델과 domain tests만 바꿔 worker/KIS rollout이 안정적으로 이어지게 한다.

사용자 리뷰 요청 흐름

사용자 리뷰 요청은 선택된 SDD 결정 또는 선택된 Milestone lock 결정이 실구현을 차단할 때만 active CODE_REVIEW-local-G05.md사용자 리뷰 요청 섹션에 기록한다. 직접 chat 질문은 금지이며, code-review가 검증 후 실제 USER_REVIEW.md 작성 여부를 판단한다.

분석 결과

읽은 파일

  • agent-ops/rules/project/rules.md
  • agent-ops/rules/common/rules-roadmap.md
  • agent-ops/skills/common/router.md
  • agent-ops/skills/common/plan/SKILL.md
  • agent-ops/skills/common/roadmap-sdd/SKILL.md
  • agent-roadmap/current.md
  • agent-roadmap/phase/backtest-loop/PHASE.md
  • agent-roadmap/phase/backtest-loop/milestones/backtest-multi-timeframe-coverage.md
  • agent-roadmap/sdd/backtest-loop/backtest-multi-timeframe-coverage/SDD.md
  • agent-ops/rules/project/domain/domain-model/rules.md
  • agent-ops/rules/project/domain/worker/rules.md
  • agent-test/local/rules.md
  • agent-test/local/domain-model-smoke.md
  • agent-test/local/worker-smoke.md
  • packages/domain/market/types.go
  • packages/domain/market/types_test.go
  • services/worker/internal/jobs/marketdata_jobs.go
  • services/worker/internal/jobs/marketdata_jobs_test.go
  • services/worker/internal/providers/kis/daily_itemchartprice.go
  • services/worker/internal/providers/kis/daily_itemchartprice_test.go
  • services/worker/cmd/alt-worker/main.go
  • services/worker/cmd/alt-worker/main_test.go

테스트 환경 규칙

  • test_env: local
  • env rules: agent-test/local/rules.md 존재 및 정독 완료
  • matched profiles: agent-test/local/domain-model-smoke.md, agent-test/local/worker-smoke.md
  • 적용 명령: domain-only 선행 작업은 go test ./packages/domain/...; worker call-site compile 확인은 go test ./services/worker/...
  • fallback: 없음

테스트 커버리지 공백

  • 현재 packages/domain/market/types_test.go는 daily bar import gate만 검증하고 provider/market/venue/asset type/timeframe matrix와 rejected reason을 검증하지 않는다.
  • 현재 worker tests는 daily import handler가 old RequireDailyBars를 호출한다는 경로만 검증한다. 이 plan은 worker rollout을 하지 않으므로 worker rejected case는 후속 02+01_kis_job_capability에서 닫는다.

심볼 참조

  • 변경 대상 심볼: market.ProviderCapability, ProviderCapability.SupportsDailyBars, ProviderCapability.RequireDailyBars
  • call sites:
    • packages/domain/market/types_test.go
    • services/worker/internal/jobs/marketdata_jobs.go
    • services/worker/internal/jobs/marketdata_jobs_test.go
    • services/worker/internal/providers/kis/daily_itemchartprice.go
    • services/worker/cmd/alt-worker/main.go

분할 판단

  • split decision policy를 plan 파일 선택 전에 적용했다.
  • shared task group: agent-task/m-backtest-multi-timeframe-coverage/
  • sibling subtasks:
    • 01_domain_capability_matrix: domain capability request/decision/rule API와 domain tests. predecessor 없음.
    • 02+01_kis_job_capability: KIS capability table과 worker job gate rollout. 01_domain_capability_matrixcomplete.log 필요.
  • split 이유: shared domain API/foundation과 worker/KIS call-site rollout이 분리되는 API-vs-call-site boundary다. 첫 번째 작업이 실패해도 worker wiring 계획을 다시 쓰지 않게 한다.

범위 결정 근거

  • 포함: packages/domain/market/types.go, packages/domain/market/types_test.go
  • 제외: .proto, API socket, CLI runner, monthly aggregation, minute provider import, worker job handler 실제 변경. 이 plan은 S02 완료를 주장하지 않고 foundation만 만든다.

빌드 등급

  • build: local-G05
  • review: local-G05
  • 근거: shared domain API 변경이지만 범위가 두 파일로 작고, call-site compile을 후속 task에서 명시적으로 처리한다.

구현 체크리스트

  • ProviderCapability를 provider/market/venue/asset type/timeframe matrix request와 accepted/rejected decision을 표현하도록 확장하되, 후속 rollout 전 기존 daily call site가 컴파일될 수 있는 호환 wrapper를 유지한다.
  • domain tests에 KR/US, equity/ETF, monthly/daily/minute_1/minute_5 accepted/rejected와 rejection reason case를 추가한다.
  • go test ./packages/domain/...go test ./services/worker/...를 실행해 domain behavior와 기존 worker call-site compile을 확인한다.
  • CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

[API-1] Domain capability matrix API

문제: packages/domain/market/types.go:103ProviderCapability는 venue/timeframe map만 갖고, packages/domain/market/types.go:123RequireDailyBars는 daily 전용이라 asset type과 arbitrary timeframe rejection reason을 표현할 수 없다.

해결 방법: ProviderCapabilityRequest, ProviderCapabilityDecision, ProviderCapabilityRule를 추가한다. ProviderCapability.CheckBars(req) 또는 동등한 이름의 pure function이 provider mismatch, missing venue, unknown venue, market/venue mismatch, asset type mismatch, unsupported timeframe을 stable reason으로 반환하게 한다. 기존 RequireDailyBars(provider, selector)CheckBars에 daily + empty asset type request를 위임하는 wrapper로 남겨 후속 rollout 전 컴파일을 유지한다.

Before:

// packages/domain/market/types.go:107
type ProviderCapability struct {
	Provider   Provider
	Venues     map[Venue]bool
	Timeframes map[Timeframe]bool
}

// packages/domain/market/types.go:123
func (c ProviderCapability) RequireDailyBars(provider Provider, selector UniverseSelector) error {

After:

type ProviderCapability struct {
	Provider Provider
	Rules    []ProviderCapabilityRule
}

type ProviderCapabilityRule struct {
	Market     Market
	Venue      Venue
	AssetTypes map[AssetType]bool
	Timeframes map[Timeframe]bool
}

type ProviderCapabilityRequest struct {
	Provider  Provider
	Market    Market
	Venue     Venue
	AssetType AssetType
	Timeframe Timeframe
}

type ProviderCapabilityDecision struct {
	Accepted bool
	Reason   string
}

수정 파일 및 체크리스트:

  • packages/domain/market/types.go: matrix request/decision/rule 타입 추가
  • packages/domain/market/types.go: CheckBars 또는 동등한 판정 함수 추가
  • packages/domain/market/types.go: 기존 SupportsDailyBars/RequireDailyBars를 새 판정 함수 wrapper로 유지하거나 명시적으로 deprecate comment를 남긴다
  • packages/domain/market/types.go: rejection reason 문자열은 테스트에서 검증 가능한 stable text로 둔다

테스트 작성: packages/domain/market/types_test.goTestProviderCapabilityMatrix를 추가한다. KIS-like matrix로 KR/KRX equity daily, US/NASDAQ equity daily, US/NASDAQ ETF daily는 accepted, monthly/minute_1/minute_5는 rejected reason 포함으로 검증한다. provider mismatch, unknown venue, market/venue mismatch, unsupported asset type도 포함한다.

중간 검증:

go test ./packages/domain/...

기대 결과: exit code 0.

[API-2] Compatibility compile guard

문제: services/worker/internal/jobs/marketdata_jobs.go:113capability.RequireDailyBars(...)를 호출하고, services/worker/internal/providers/kis/daily_itemchartprice.go:32는 기존 struct literal을 반환한다. domain foundation 변경이 worker rollout보다 먼저 merge되면 worker compile이 깨질 수 있다.

해결 방법: domain API에 compatibility wrapper와 old-style construction migration path를 함께 둔다. old Venues/Timeframes 필드를 제거하지 않고 deprecated 호환 필드로 유지하거나, same-plan에서 worker helper test constructors까지 최소 수정한다. 후속 task가 KIS/job gate를 새 matrix API로 전환한다.

수정 파일 및 체크리스트:

  • packages/domain/market/types.go: old call site compatibility 전략 적용
  • packages/domain/market/types_test.go: old RequireDailyBars wrapper가 daily accepted/rejected를 유지하는 회귀 테스트 보존

테스트 작성: 기존 TestProviderCapabilityRequireDailyBars를 유지하거나 matrix API 기반으로 갱신하되, daily wrapper의 기존 KR/US accepted와 provider/venue rejection이 유지되는 assertion을 둔다.

중간 검증:

go test ./services/worker/...

기대 결과: exit code 0.

수정 파일 요약

파일 항목
packages/domain/market/types.go API-1, API-2
packages/domain/market/types_test.go API-1, API-2

최종 검증

go test ./packages/domain/... ./services/worker/...

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

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