From cec34be5f4249241356eb6805ad64c151bb23ff4 Mon Sep 17 00:00:00 2001 From: Justin Ko Date: Wed, 10 Jun 2026 12:36:09 +0900 Subject: [PATCH] =?UTF-8?q?docs(batch):=20draft-batch=20BAT-030=20(dcy-020?= =?UTF-8?q?=20BAT-=CE=B4=20cutover)=20+=20design=20=ED=99=95=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dcy-020 최종 배치. design 확정(사용자 결정): - D1: 전체 rebuild — daily_slot 비우고 universe+브로커 잔고 기준 재생성, 보유 carry-over 정본=브로커 잔고 - D2: 전부 완성 — literal inactive 전면화 + idle/closed 별칭 제거 + entry_count/trading_date 컬럼 drop - D3: 집행 매도 수량 브로커 정본(미러 fallback 없음, 0이면 skip+divergence) - D4: 실 cutover 는 운영자(REL 단계, 리허설 후); 본 배치는 스크립트+코드+test DB 리허설 batches/index BAT-030 등록. Co-Authored-By: Claude Opus 4.8 --- .../design.md | 47 +++++++++++++++++++ .../implementation.md | 16 +++++++ .../index.md | 32 +++++++++++++ .../planning.md | 44 +++++++++++++++++ .../verification.md | 13 +++++ docs/batches/index.md | 1 + 6 files changed, 153 insertions(+) create mode 100644 docs/batches/bat-030_20260610_asset-centric-cutover/design.md create mode 100644 docs/batches/bat-030_20260610_asset-centric-cutover/implementation.md create mode 100644 docs/batches/bat-030_20260610_asset-centric-cutover/index.md create mode 100644 docs/batches/bat-030_20260610_asset-centric-cutover/planning.md create mode 100644 docs/batches/bat-030_20260610_asset-centric-cutover/verification.md diff --git a/docs/batches/bat-030_20260610_asset-centric-cutover/design.md b/docs/batches/bat-030_20260610_asset-centric-cutover/design.md new file mode 100644 index 0000000..b078c0d --- /dev/null +++ b/docs/batches/bat-030_20260610_asset-centric-cutover/design.md @@ -0,0 +1,47 @@ +# BAT-030 Design + +- Status: confirmed (D1~D4 확정 — 2026-06-10, 사용자 결정) +- Batch: BAT-030 + +> **체크포인트 결정(2026-06-10)**: D1=**전체 rebuild**(보유는 브로커 잔고 기준 carry-over) / D2=**전부 완성**(literal inactive + 별칭 제거 + entry_count·trading_date drop) / D3=**집행 매도 qty 브로커 정본**(미러 fallback 없음, 0이면 skip+divergence) / D4=**실 cutover 는 운영자(REL 단계, 리허설 후)**. 아래 §1 을 전체 rebuild 로 읽는다. + +## 설계 목표 +- 자산 중심 모델을 완성하고 라이브로 안전 전환. 보유 포지션 무손실·집행 정확·비가역 변경 통제. + +## 1. cutover (REQ-064) — 전체 rebuild (D1) +- **전체 rebuild**: 해당 instance_key 의 daily_slot 을 비우고 universe + 브로커 잔고 기준으로 재생성한다. **보유 carry-over 의 정본 = 브로커 잔고**(D3 와 일관). +- 절차(cutover 스크립트, Python — broker + universe 필요): + 1. 사전: 거래 세션 외, in-flight(pending_*) 0 확인(아니면 수렴 대기). 백업. + 2. 해당 instance_key 슬롯 삭제(또는 신규 테이블 swap). + 3. universe(get_portfolios) 의 모든 자산 → 영구 슬롯 생성(`inactive`). + 4. 브로커 잔고(get_balance)의 각 보유 (symbol, qty) → universe 로 symbol→portfolio_id 매핑 → 해당 자산 슬롯을 `holding`(qty=브로커 수량, avg_price=브로커/원장) 으로 설정. + 5. instance_key 태깅, 부분 UNIQUE → 전체 UNIQUE 승격. +- 매핑 실패(브로커 보유 symbol 이 universe 에 없음) → 중단/경고(운영자 판단; 자동 청산 없음). +- **실 cutover 는 운영자 실행**(D4) — 본 배치는 cutover 스크립트 + test DB 리허설 제공. + +## 2. 집행 매도 수량 브로커 정본 (REQ-062 M2(b)) +- `execution.py` dispatch: 매도 시 `qty = int(slot.qty)` → `broker.get_balance()` 의 해당 symbol `hldg_qty`. 미러 stale 무관 정확. 브로커 0 이면 매도 skip + divergence(REQ-062 A) 경로로 표면화. + +## 3. literal inactive 전면화 (REQ-057 잔여) +- `state.py`: `idle`/`closed` 별칭 제거(또는 deprecated 유지하되 코드 산출은 inactive). 전이/리셋이 `inactive` 산출. +- `execution.py`: PENDING_SELL→`INACTIVE`(매도 체결), PENDING_BUY→`INACTIVE`(롤백). postgresql/cli/ops_checks 의 `'idle'`/`'closed'` → `'inactive'`(쿼리/필터). +- **마이그레이션 010(CHECK)**: status CHECK 에 `'inactive'` 허용 + 기존 `idle`/`closed` 행 → `inactive` UPDATE. + +## 4. 컬럼 drop (REQ-056 잔여) +- `entry_count` drop(미사용). 슬롯 `trading_date`: drop 또는 `opened_at` 재의미(이벤트 시간 속성으로). 모델/`EXPECTED_SLOT_FIELDS`/persistence/드리프트 가드 정합. legacy preallocation 경로 제거. +- 비가역 → drop 전 코드 미참조화 선행, 백업, 롤백(직전 리비전+컬럼 복원). + +## 5. default 전환 +- 코드 default 변경 아님 — **운영 인스턴스 TOML 에 `max_active_slots` 설정**으로 자산 중심 활성(config 게이트). 배포 단계 운영자 작업. + +## 6. baseline 마감 (REQ-065) +- data-model/runtime-flows/project-structure 를 최종 자산 중심으로 갱신, dcy-001/014/019·daily_symbol_entries 폐기 확정. + +## 롤백 +- 직전 released 리비전 + (필요시) 역마이그레이션(inactive→idle/closed, 컬럼 복원). 보유 행은 portfolio_id 보존이라 구 코드와 공존(부분). 컬럼 drop 은 백업 복원. + +## 체크포인트 결정 필요 +1. **D1 — cutover 방식**: 보유 행 재사용 + vestigial idle 삭제 + reconcile(권장) vs 전체 rebuild. +2. **D2 — 본 배치 완성 범위**: literal inactive + 별칭 제거 + entry_count/trading_date drop **전부 완성**(권장) vs 일부 유지. +3. **D3 — 집행 매도 qty**: 브로커 정본(미러 fallback 없음, 0이면 skip+divergence)(권장) 확인. +4. **D4 — 실 cutover 실행 주체**: 운영자(REL 단계, 리허설 후)(권장) — 본 세션은 마이그레이션+코드+test DB 리허설까지. diff --git a/docs/batches/bat-030_20260610_asset-centric-cutover/implementation.md b/docs/batches/bat-030_20260610_asset-centric-cutover/implementation.md new file mode 100644 index 0000000..ad013d6 --- /dev/null +++ b/docs/batches/bat-030_20260610_asset-centric-cutover/implementation.md @@ -0,0 +1,16 @@ +# BAT-030 Implementation + +- Status: not-started +- Batch: BAT-030 + +## 구현 요약 +- (run-batch-delivery 진입 시 작성) design.md 체크포인트(D1~D4) 확정 후 채운다. + +## 변경 내역 +- (대기) + +## 테스트 +- (대기) + +## 검증 실행 +- (대기) diff --git a/docs/batches/bat-030_20260610_asset-centric-cutover/index.md b/docs/batches/bat-030_20260610_asset-centric-cutover/index.md new file mode 100644 index 0000000..369abdd --- /dev/null +++ b/docs/batches/bat-030_20260610_asset-centric-cutover/index.md @@ -0,0 +1,32 @@ +# BAT-030: 자산 중심 cutover — 라이브 전환·집행 정본·모델 완성 (dcy-020 BAT-δ) + +- Status: planning +- Profile: standard +- Source Discovery: dcy-020 +- Included REQ: REQ-064 (풀→영구 cutover), REQ-062 (잔여: 청산 수량 브로커 정본), REQ-056/057/065 (잔여: entry_count/trading_date drop·literal inactive·baseline 마감) + +## Summary +- dcy-020 의 **마지막 배치(BAT-δ)** — 자산 중심 모델을 **완성하고 라이브로 전환**한다. 가장 위험: 라이브 트레이딩 데이터 cutover + 집행 동작 변경 + 모델 완성(별칭/컬럼 정리). +- 핵심: (1) 라이브 cutover(풀 행→영구 자산 행, 보유 carry-over, instance_key 태깅), (2) 집행 dispatch 매도 수량 = **브로커 잔고 정본**(REQ-062 잔여, M2(b)), (3) literal `inactive` 전면화 + `idle`/`closed` 별칭 제거 + CHECK 제약 갱신, (4) `entry_count`/슬롯 `trading_date` 컬럼 drop, (5) 자산 중심 default 운영 전환(max_active_slots), (6) baseline 문서 마감(REQ-065). + +## Scope +- In Scope: + - REQ-064: cutover 마이그레이션 + 절차 + 롤백(라이브는 운영자 실행) + - REQ-062 잔여: execution dispatch 매도 수량 브로커 잔고 정본(M2(b)) + - REQ-056/057 잔여: literal inactive(+CHECK 마이그레이션), idle/closed 별칭 제거, entry_count/trading_date 컬럼 drop + - REQ-065: baseline 3문서 마감 + dcy-001/014/019 폐기 확정 + - 자산 중심 default 전환(운영 config) + run-the-app(자산 중심 e2e) +- Out of Scope: + - 포지션 사이징(issue #1, OQ-4 분리 — 후속 Discovery) + - 신규 기능(본 배치는 모델 완성·전환만) + +## Documents +- Planning: [planning.md](./planning.md) +- Design: [design.md](./design.md) +- Implementation: [implementation.md](./implementation.md) +- Verification: [verification.md](./verification.md) + +## Notes +- Source discovery 단일(dcy-020). BAT-027/028/029 후속, dcy-020 최종. +- **최고 위험**: 라이브 데이터·집행 전환. **실 cutover 는 운영자 실행**(본 배치는 마이그레이션·코드·리허설 제공). design 체크포인트에서 cutover 절차·롤백·운영자 입회·전환 순서 확정 후 구현. +- 본 배치 완료 후 REQ-056~065 confirm-req-implemented → REL. diff --git a/docs/batches/bat-030_20260610_asset-centric-cutover/planning.md b/docs/batches/bat-030_20260610_asset-centric-cutover/planning.md new file mode 100644 index 0000000..85a3779 --- /dev/null +++ b/docs/batches/bat-030_20260610_asset-centric-cutover/planning.md @@ -0,0 +1,44 @@ +# BAT-030 Planning + +- Status: confirmed +- Batch: BAT-030 +- Profile: standard + +## Included REQ +- REQ-064 (Migration, Approved): 풀→영구 자산 슬롯 cutover + 롤백. +- REQ-062 (Integration, Approved 잔여): 청산 수량 브로커 정본(M2(b), execution dispatch). +- REQ-056/057 (잔여): entry_count/trading_date 컬럼 drop, literal inactive + 별칭 제거. +- REQ-065 (Documentation): baseline 마감. + +## Delivery Plan (전환 순서 — 안전 우선) +1. **literal inactive 전면화**: `state.py` IDLE/CLOSED 별칭 제거(또는 deprecate), 코드가 `inactive` 산출. `execution.py` PENDING_SELL→`INACTIVE`·PENDING_BUY→`INACTIVE`. postgresql/cli/ops_checks 의 'idle'/'closed' → 'inactive'. CHECK 제약 마이그레이션(010: 'inactive' 허용 + 기존 idle/closed→inactive UPDATE). +2. **M2(b) 집행 매도 수량 브로커 정본**: dispatch 매도 `int(slot.qty)` → `broker.get_balance()` 해당 symbol hldg_qty. 미러 stale 무관 정확. +3. **컬럼 drop**: `entry_count`·슬롯 `trading_date`(또는 opened_at 재의미) drop 마이그레이션 + 모델/EXPECTED_SLOT_FIELDS/persistence 정합. (legacy preallocation 경로도 제거.) +4. **cutover 마이그레이션(REQ-064)**: 기존 보유(holding, portfolio_id 보유) 행은 그대로 자산 슬롯; vestigial idle 풀 행(portfolio_id NULL) 정리; instance_key 태깅(009 default 'default'); UNIQUE 부분→전체 승격 검토. +5. **default 전환**: 운영 인스턴스 TOML 에 `max_active_slots` 설정(자산 중심 활성) — 운영자 배포 단계. +6. **baseline 마감(REQ-065)** + run-the-app 자산 중심 e2e(test DB). + +## Dependencies +- Internal: BAT-027/028/029(스키마·상태머신·reconcile·admission·divergence). 전 단계 green. +- External: 전략 모듈 slot_id 계약 전환(BAT-029 dual-accept 로 무중단; portfolio_id 매수 폐기 시 전략 전환 필요). + +## Design Gate +- Design Required Before Implementation: yes +- Reason: (a) **라이브 데이터 cutover** — 보유 포지션 무손실·롤백·in-flight(pending) 처리·운영자 입회 절차를 설계에서 확정. (b) literal inactive 전환은 BAT-027 별칭의 역-cascade(코드+CHECK 마이그레이션+다수 테스트). (c) 집행 dispatch 매도 수량 변경은 라이브 주문 동작. (d) 컬럼 drop 은 비가역 — 순서·롤백 필수. → design.md 확정 후 구현 전 체크포인트. + +## Milestones +1. M1 — literal inactive + CHECK 마이그레이션(010) + 별칭 제거 + 테스트 +2. M2 — 집행 매도 수량 브로커 정본 +3. M3 — entry_count/trading_date drop 마이그레이션 + 정합 +4. M4 — cutover 마이그레이션(REQ-064) + 리허설(test DB) +5. M5 — baseline 마감 + run-the-app 자산 중심 e2e + +## Risks +- R-live (High): 라이브 cutover 로 보유 포지션 손실/집행 중단. 대응: 보유 행 보존(이미 portfolio_id 보유)·거래 세션 외 실행·롤백 스크립트·운영자 입회·리허설(test DB) 선행. +- R-irreversible (High): 컬럼 drop 비가역. 대응: drop 전 백업, 단계적(코드 미참조화 → drop), 롤백은 직전 리비전+컬럼 복원. +- R-cascade (Medium): literal inactive 역전환의 테스트/코드 cascade. 대응: BAT-027 별칭 지점 일괄 전환 + 회귀 green 게이트. +- R-exec (Medium): 집행 매도 qty 변경 회귀. 대응: 단위+리허설, 미러 fallback 없이 broker 권위. + +## Notes +- 실 cutover 는 운영자 실행(본 배치는 마이그레이션·코드·리허설 제공). confirm-release 전 cutover 리허설 + run-the-app evidence 필수. +- green 기준: 단위 전체 회귀(literal inactive·drop 무파손) + cutover 리허설(보유 보존·롤백) + 자산 중심 e2e. diff --git a/docs/batches/bat-030_20260610_asset-centric-cutover/verification.md b/docs/batches/bat-030_20260610_asset-centric-cutover/verification.md new file mode 100644 index 0000000..c4742f9 --- /dev/null +++ b/docs/batches/bat-030_20260610_asset-centric-cutover/verification.md @@ -0,0 +1,13 @@ +# BAT-030 Verification + +- Status: not-started +- Batch: BAT-030 + +## Acceptance Mapping +- (draft-batch-verification / confirm-batch-verification 단계에서 작성) + +## Evidence +- (대기) + +## Result +- Ready for Release: false (구현 전) diff --git a/docs/batches/index.md b/docs/batches/index.md index e2bc6b8..0c5ad72 100644 --- a/docs/batches/index.md +++ b/docs/batches/index.md @@ -37,3 +37,4 @@ | BAT-027 | standard | planning | REQ-056, REQ-057 | dcy-020 (BAT-α) | [bat-027](./bat-027_20260610_asset-permanent-slot-foundation/) | | BAT-028 | standard | planning | REQ-058, REQ-059, REQ-060 | dcy-020 (BAT-β) | [bat-028](./bat-028_20260610_universe-reconcile-and-active-admission/) | | BAT-029 | standard | planning | REQ-061, REQ-062, REQ-063 | dcy-020 (BAT-γ) | [bat-029](./bat-029_20260610_asset-keyed-intent-and-divergence/) | +| BAT-030 | standard | planning | REQ-064, REQ-062, REQ-056·057·065(잔여) | dcy-020 (BAT-δ) | [bat-030](./bat-030_20260610_asset-centric-cutover/) |