Files
trex-core/docs/batches/bat-030_20260610_asset-centric-cutover/verification.md
T
genichinandClaude Opus 4.8 5330f32247 docs(batch): BAT-030 verification 승인 + REQ-056~065 Implemented (dcy-020 delivery 완료)
draft/confirm-batch-verification: BAT-030 AC 매핑(REQ-056·057·062·064·065) +
evidence(단위 367/PG 29/MQ 21, cutover 리허설 8건, run-the-app e2e) 기록,
Ready for Release: true → release-candidate 승격.
BAT-027/028/029 의 보류 사유(dcy-020 전체 delivery 미완)가 BAT-030 완성으로
해소되어 함께 release-candidate 승격.
confirm-req-implemented: REQ-056~065 전부 Approved → Implemented
(각 REQ Change Log CHG-20260610-IMPL + srs index 갱신).
실 운영 cutover(REQ-064)는 REL 단계 운영자 실행으로 위임.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 15:20:52 +09:00

6.9 KiB
Raw Blame History

BAT-030 Verification

  • Status: approved (confirm-batch-verification, 2026-06-10)
  • Batch: BAT-030
  • 일자: 2026-06-10
  • 검증 환경: Python 3.12 / PostgreSQL trex_core_test(실 DB) / 실 RabbitMQ / paper broker

Acceptance Mapping

REQ-056 (Data — 잔여: trading_date/entry_count drop, 스키마 마감)

AC 판정 Evidence
AC-1 스키마: portfolio_id NOT NULL·instance_key·UNIQUE(instance_key,portfolio_id)·retired_at·trading_date/entry_count 부재 pass (NOT NULL 은 promote 후) 마이그레이션 009/010/011 + test_promote_unique_sets_not_null(cutover --promote-unique 로 NOT NULL 승격 — 공유 DB 전 인스턴스 cutover 후 적용하는 설계, BAT-027 결정); test_daily_slot_columns_match_expected_contract(drop 후 컬럼셋 일치)
AC-2 EXPECTED_SLOT_FIELDS ↔ information_schema 일치 pass tests/adapters/persistence/test_migration_and_drift.py 3건 PG 통과
AC-3 (instance_key, portfolio_id) 중복 거부 pass partial UNIQUE(009) + test_universe_reconcile_pg(ON CONFLICT 멱등, created=0)
AC-4 인스턴스 간 행 미혼합 pass test_dispatch_queue_instance_scoped(집행 큐 격리) + test_instance_isolation(reconcile) + cutover test_instance_isolation_other_instance_untouched

REQ-057 (Interface — 잔여: literal inactive + 별칭 제거)

AC 판정 Evidence
AC-1 허용 전이 집합 정확 일치(12종) pass tests/domain/slot/test_state.py(5 members·alias ValueError·allowed/disallowed 파라미터라이즈·set size 12)
AC-2 매도 체결 → inactive 복귀(closed 없음)·점유 clear pass test_sell_fill_returns_to_inactive_and_clears_position, test_full_lifecycle_returns_to_inactive_and_reuses(PG), e2e 7단계(status=inactive, qty=None)
AC-3 인스턴스별 락 비차단 pass slot_advisory_lock_id 인스턴스 해시(BAT-027) + test_slot_advisory_lock_id_is_instance_scoped
AC-4 동일 슬롯 동시 전이 직렬화 pass TestAdvisoryLockSerialization(1 success/1 mismatch)

REQ-062 (Integration — 잔여: M2(b) 매도 수량 브로커 정본)

AC 판정 Evidence
AC-1 매도 수량 = 브로커 잔고(미러 stale 무관) pass test_sell_qty_is_broker_balance_not_slot_mirror(미러 7 vs 브로커 10 → 주문 10) + test_sell_skipped_when_broker_flat(브로커 0 → skip+카운터, 주문 0) + test_skipped_sell_does_not_block_other_dispatches
AC-2 core holding/브로커 0 → error 격리 pass (BAT-029 기구현) tests/application/test_holding_divergence.py::test_A_* — 본 배치에서 회귀 green 재확인
AC-3 core flat/브로커 보유 → WARN·운영자 결정 pass (BAT-029 기구현; 슬롯 부재로 '격리' 대신 unmanaged WARN — issue #15 무자동조치 결정) test_B_broker_holds_unmanaged_warns
AC-4 수량 불일치 → 상태 전이 없음·warning 노출 pass (BAT-029 기구현; 미러 자동 갱신 없이 WARN — 보수 구현) test_C_qty_mismatch_warns_no_state_change

REQ-064 (Migration — cutover + 롤백)

AC 판정 Evidence
AC-1 보유 N개 → 영구 슬롯 holding 보존(수량 무유실) pass (리허설) tests/runtime/test_cutover_rehearsal.py::test_full_rebuild_with_broker_carry_over — 브로커 qty=12 정본 carry-over(미러 7 아님), 자산 바인딩 보존. ※ avg_price 는 잔고 API 미제공으로 NULL carry(+WARN) — implementation.md 잔여 리스크
AC-2 cutover 후 데몬 회귀 없음(reconcile·admission·safety-sell) pass run-the-app e2e(아래) + 단위 367/PG 29 green
AC-3 실패 시 롤백 가능 pass (계획+부분 검증) 단일 트랜잭션(중단 시 무변경: test_aborts_on_in_flight_pending/test_aborts_on_unmapped_broker_holding DB 불변 단언) + test_dry_run_rolls_back; 전체 롤백 = 백업 복원 + 직전 리비전(design §롤백, 운영 절차)
AC-4 instance_key 태깅·스코프 쿼리 정확 pass cutover 가 instance_key 로 생성 + test_instance_isolation_other_instance_untouched

REQ-065 (Documentation — baseline 마감)

AC 판정 Evidence
AC-1 data-model.md 코드 일치 pass commit 7d72782 — 영구 슬롯 스키마·5-state·trading_date 강등(전이 로그/원장으로)·INACTIVE 리셋 규칙 반영
AC-2 runtime-flows.md 일치 + preallocation 서술 제거 pass 데몬 7스레드·universe reconcile 흐름(preallocation 대체)·admission slot_id·매도 브로커 정본·transit 12전이 갱신
AC-3 폐기 범위 명시(dcy-001/014/019·daily_symbol_entries) pass data-model Model Summary/Gaps + Change Log; project-structure·interface-contract 도 동기화(추가)

Evidence

  1. 단위 회귀: pytest tests → 367 passed, ruff All checks passed (commit 7d72782 시점).
  2. PG-gated(실 PostgreSQL trex_core_test): 29 passed — 마이그레이션 001~011 전체 재적용 멱등(test_apply_migrations_is_idempotent; 010 CHECK drop-and-add·011 DROP IF EXISTS·008 no-op 가 매 boot 재실행에 안전함을 모든 PG 테스트의 pg_clean 반복 적용으로 입증), 컬럼 드리프트 가드, reconcile/admission/lifecycle, dispatch 인스턴스 격리, ops_checks(transition_log 기반) 3건, cutover 리허설 8건.
  3. RabbitMQ-gated(실 브로커): 21 passed — slot_id 계약 포함 intent RPC e2e dedup.
  4. run-the-app e2e(test DB + 실 RabbitMQ + paper broker, instance=e2etest, M=1): boot reconcile created=2 → snapshot(slots=2 inactive, available=1) → buy by slot_id admitted → 중복 intent identical → 2번째 자산 capacity_full → fill→holding(available=0) → 동일 슬롯 already_active → sell→fill→inactive(qty=None·portfolio_id 보존·available=1) → 동일 영구 슬롯 재매수 admitted. DB 최종행·transition_log·ledger_outbox(completed×3) 일치, 데몬 로그 ERROR/Traceback 0, SIGTERM Normal shutdown. (전 과정 implementation.md 검증 실행 절 기록)
  5. baseline 동기화(Architecture Impact 有): data-model/runtime-flows/project-structure/interface-contract 4문서 + run-trex-core-daemon 스킬 + instance.example.toml 갱신 — commit 7d72782 포함.

Blocking Issues

  • 없음 (코드/리허설 범위). 단, 실 운영 DB cutover 는 본 배치 산출물 범위 밖(design D4) — release(REL) 단계에서 운영자가 백업→리허설→trex-core-cutover --yes→운영 TOML max_active_slots 설정 순으로 수행해야 하며, 그 운영 증거는 release 검증에 귀속된다.

Result

  • 포함 REQ AC 전 항목 evidence 연결 완료(REQ-062 AC-3/4 는 issue #15 무자동조치 결정에 따른 보수 구현 — 의도된 편차로 기록).
  • Ready for Release: true (배치 산출물 기준 — 코드·마이그레이션·cutover 도구·리허설·baseline. 실 cutover 실행은 REL 단계 운영자 작업으로 release 게이트에 위임)