formula_id: WBS_10_DOTNET_MIGRATION_ROADMAP_V1 title: "WBS-10 .NET 엔진 고도화 상세 로드맵" owner: "QuantEngine" source_of_truth: - docs/ROADMAP_WBS.md - spec/60_quant_engine_wbs.yaml - spec/41_release_dag.yaml - spec/00_execution_contract.yaml scope: goal: "Python 검증/보조 도구는 유지하고, 운영 엔진은 .NET으로 수렴시키며, 테이블 구조와 스케줄러를 서비스 수준으로 고도화한다." non_goals: - "가격/수량/임계값의 LLM 즉석 계산" - "운영 경로의 Python 재도입" - "원천 데이터의 무분별한 중복 저장" principles: - "Python은 harness, verification, conversion tooling에 집중한다." - ".NET은 runtime engine, scheduler, API, operational read model을 담당한다." - "쓰기 경로는 정규화, 읽기 경로는 의도된 역정규화로 분리한다." - "모든 숫자는 provenance와 검증 아티팩트를 가져야 한다." - "스케줄러는 단순 cron이 아니라 상태/의존성/재시도/감사 추적을 갖는 서비스로 취급한다." roadmap: phase_name: "WBS-10 .NET 엔진 고도화" phase_goal: "Python-to-.NET 전환, 테이블 정규화/역정규화, 서비스급 스케줄러, parity harness 정착" exit_gate: "dotnet runtime parity PASS + scheduler observability PASS + normalized/denormalized schema contract PASS + evidence artifacts recorded" tracks: - track_id: WBS-10-A name: "Python → .NET 전환" description: "운영 경로에서 Python 의존을 제거하고, 동일 결과를 내는 .NET canonical 구현으로 이식한다." tasks: - task_id: WBS-10-A1 title: "실행 경로 인벤토리 및 전환 우선순위 확정" status: PENDING owner_files: - src/quant_engine/ - tools/ - spec/60_quant_engine_wbs.yaml success_data_guide: required_inputs: - "운영 진입점 목록" - "Python CLI/모듈 호출 지점" - "배포/스케줄러 호출 경로" expected_outputs: - "전환 우선순위 표" - "운영 경로 / 보조 경로 분리 결과" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-A1/verdict.json" done_when: - "운영 경로와 보조 경로가 문서화됨" - "전환 대상/비대상 경로가 분리됨" - task_id: WBS-10-A2 title: ".NET 도메인 서비스로 Python 계산 로직 이식" status: PENDING owner_files: - src/dotnet/QuantEngine.Core/ - src/dotnet/QuantEngine.Application/ success_data_guide: required_inputs: - "Python reference result" - "현재 .NET implementation" - "golden parity dataset" expected_outputs: - "동일 입력에 대한 .NET 결과" - "Python 대비 parity diff 0 또는 허용오차 내" verification_commands: - "dotnet test src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj -c Release" - "python tools/verify_wbs_task_v1.py --task WBS-10-A2" evidence_artifacts: - "Temp/evidence/WBS-10-A2/verdict.json" done_when: - "Python reference와 .NET output이 parity를 만족" - "핵심 계산이 서비스 계층으로 이동됨" - task_id: WBS-10-A3 title: "Python thin-wrapper 정리 및 운영 금지 경로 분리" status: PENDING owner_files: - tools/ - src/quant_engine/ success_data_guide: required_inputs: - "현재 Python script 목록" - "runtime entrypoint 목록" expected_outputs: - "운영용 thin wrapper만 남김" - "직접 운영 경로 금지 목록" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-A3/verdict.json" done_when: - "운영 진입점이 .NET 또는 thin wrapper로만 남음" - track_id: WBS-10-B name: "테이블 정규화 + 역정규화" description: "원천/원장/배포 이력을 정규화하고, UI/대시보드용 읽기 모델은 역정규화한다." tasks: - task_id: WBS-10-B1 title: "정규화 기준 테이블 계약 확정" status: PENDING owner_files: - spec/ - src/dotnet/QuantEngine.Infrastructure/ success_data_guide: required_inputs: - "source table 목록" - "primary key / foreign key 정의" - "중복 제거 대상" expected_outputs: - "canonical normalized schema" - "table ownership map" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-B1/verdict.json" done_when: - "쓰기 경로의 canonical table contract가 문서화됨" - task_id: WBS-10-B2 title: "운영 조회용 역정규화 read model 설계" status: PENDING owner_files: - src/dotnet/QuantEngine.Web/ - src/dotnet/QuantEngine.Application/ success_data_guide: required_inputs: - "대시보드/운영 화면 요구사항" - "조회 성능 목표" expected_outputs: - "읽기 전용 denormalized projection" - "refresh/update strategy" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-B2/verdict.json" done_when: - "읽기 모델이 원천 원장과 분리됨" - "운영 화면이 read model만 참조함" - task_id: WBS-10-B3 title: "중복/파생 데이터 경계 및 기술부채 방지 계약" status: PENDING owner_files: - spec/ - governance/ success_data_guide: required_inputs: - "allowed denormalization cases" - "forbidden duplication cases" expected_outputs: - "파생 데이터 허용 규칙" - "canonical source 정의" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-B3/verdict.json" done_when: - "역정규화가 의도된 캐시/서빙으로만 허용됨" - track_id: WBS-10-C name: "서비스 수준 스케줄러" description: "cron 수준을 넘어 상태 머신, idempotency, dependency, audit, retry를 갖는 스케줄러로 강화한다." tasks: - task_id: WBS-10-C1 title: "스케줄러 상태 머신 및 실행 이력 계약" status: PENDING owner_files: - src/dotnet/QuantEngine.Application/ - src/dotnet/QuantEngine.Web/Services/ success_data_guide: required_inputs: - "job state list" - "transition rule" - "run id / lease key" expected_outputs: - "pending/running/succeeded/failed/retrying/blocked 상태 정의" - "audit trail schema" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-C1/verdict.json" done_when: - "스케줄러의 상태 전이가 데이터로 설명됨" - task_id: WBS-10-C2 title: "idempotency 및 concurrency control" status: PENDING owner_files: - src/dotnet/QuantEngine.Application/ - spec/41_release_dag.yaml success_data_guide: required_inputs: - "중복 실행 시나리오" - "동시 실행 금지 자원 목록" expected_outputs: - "중복 적재 방지" - "자원별 lock/lease 정책" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-C2/verdict.json" done_when: - "같은 run이 두 번 실행돼도 결과가 중복되지 않음" - task_id: WBS-10-C3 title: "health gate + retry policy + dependency graph" status: PENDING owner_files: - .gitea/workflows/ - src/dotnet/QuantEngine.Web/ success_data_guide: required_inputs: - "업스트림 의존성 목록" - "retry 가능한 failure 유형" - "health check 대상" expected_outputs: - "ci -> prepare-release -> deploy-prod 순차 게이트" - "transient failure만 재시도" verification_commands: - "python tools/validate_quant_engine_wbs_v1.py" evidence_artifacts: - "Temp/evidence/WBS-10-C3/verdict.json" done_when: - "스케줄러가 선행 성공 없이는 후속 실행을 시작하지 않음" deliverables: - "docs/WBS_10_DOTNET_MIGRATION_ROADMAP.yaml" - "AGENTS.md routing update" - "필요 시 docs/ROADMAP_WBS.md에 pointer 추가" alignment: canonical_status: "supplementary" canonical_note: "이 YAML은 기존 WBS-10의 상세 실행 가이드이며, 권위는 docs/ROADMAP_WBS.md와 spec/60_quant_engine_wbs.yaml에 남긴다." spec_task_map: WBS-10.1: WBS-10-A1 WBS-10.2: WBS-10-C1 WBS-10.3: WBS-10-A2 WBS-10.4: WBS-10-A2 WBS-10.5: WBS-10-A2 WBS-10.6: WBS-10-C2 WBS-10.7: WBS-10-B2 WBS-10.8: WBS-10-C3 WBS-10.9: WBS-10-B3 WBS-10.10: WBS-10-B2 WBS-10.11: WBS-10-A3 WBS-10.12: WBS-10-C3