# BAT-025 Planning - Status: confirmed - Batch: BAT-025 - Profile: standard ## Included REQ - REQ-002 (Interface, change-req): `Slot.entry_count` 필드 + `EXPECTED_SLOT_FIELDS`, 상태 머신 `closed→pending_buy` 신규 전이, `_apply_transition_fields` clean-slate + entry_count +1. - REQ-003 (Testing, change-req): 전이 카운트(14→15)·필드셋 계약 가드 정합 + entry_count/reallocation 신규 단위 테스트. - REQ-006 (Data, change-req): 멱등 마이그레이션 008 + flat slot 매핑 + `find_allocatable_slot` selector. - REQ-007 (Interface, change-req): `_admit_buy` find_idle_slot→find_allocatable_slot + from_state=slot.status. - REQ-009 (Documentation, change-req): data-model/runtime-flows baseline 정합. ## Delivery Plan 1. REQ-002 도메인: `models.py` `Slot.entry_count`(기본 0)+`EXPECTED_SLOT_FIELDS`; `state.py` `_BASE_TRANSITIONS` 에 `closed→pending_buy`; `service.py` `_apply_transition_fields` closed→pending_buy clean-slate 점유 초기화 + 모든 `→pending_buy` 시 `entry_count`+1. 2. REQ-006 영속화: `sql/008_add_slot_entry_count.sql`(ADD COLUMN IF NOT EXISTS, 기본 0); `postgresql.py` `_SLOT_COLUMNS`/`update_slot`/`_row_to_slot` +entry_count; `find_allocatable_slot`(idle∪closed ORDER BY entry_count,updated_at,slot_id LIMIT 1); `repository.py` Protocol + `in_memory_repository.py` 동등. 3. REQ-007 admission: `intents.py` `_admit_buy` selector 전환 + from_state=slot.status(closed 후보 직접 재할당). 4. REQ-003 테스트: `test_state.py`(전이 14→15), `test_contract.py`(entry_count 포함은 EXPECTED 갱신으로 자동), 신규 `test_slot_entry_count.py`(증분/보존/clean-slate/selector 정렬) + `test_buy_admission_reallocation.py`(closed admit/idle 우선/양쪽 소진 reject). 5. REQ-009 문서: `data-model.md`(entry_count 필드/lifecycle/state rules), `runtime-flows.md`(admission selector/transit_slot entry_count step). 6. 단위 회귀 + ruff + (test DSN 가용 시) PG 게이트 마이그레이션/드리프트. ## Dependencies - Internal: - dcy-001/BAT-001 slot 도메인(state/models/service/repository, REQ-002/003) — 변경 대상. - dcy-002/BAT-002 PostgreSQL 영속화 + intent admission(REQ-006/007) — 변경 대상. - dcy-014/BAT-018 trading_date 경계 preallocation — entry_count 는 일자 범위 slot row 기준(불변, A-1/A-2). - External: - 없음(전부 내부 도메인/스키마). ## Design Gate - Design Required Before Implementation: yes - Reason: (a) 상태 머신 불변식 변경(8→9 base 전이) + closed→pending_buy clean-slate 의미는 도메인 계약(REQ-001/002 NFR-2)·계약 가드·기존 closed→idle 리셋과 교차 → 설계에서 전이/리셋 경계 고정. (b) admission 후보 확장(idle∪closed)이 마지막 슬롯 경합 동시성(advisory lock+재시도)·중복 카운트 없음을 깨지 않도록 selector(FOR UPDATE 미사용, find_idle_slot 동등)·증가 시점(단일 transit) 규칙을 못박아야 안전. (c) daily_slot 컬럼 추가가 `EXPECTED_SLOT_FIELDS`·flat read/write 순서를 깨면 광범위 회귀(R-3) → 모델·계약·persistence·data-model 동일 묶음 정합. → design.md 동일 턴 scaffold. ## Milestones 1. M1 — REQ-002 도메인(field/transition/service) + 전이·계약 가드 green 2. M2 — REQ-006 마이그레이션 008 + persistence 매핑 + selector + in-memory 동등 3. M3 — REQ-007 `_admit_buy` 일반화 + reallocation 단위 green 4. M4 — REQ-003 신규 단위 테스트 + REQ-009 문서 정합 5. M5 — 단위 전체 회귀 + ruff (+ test DSN PG 게이트) ## Risks - R-1 (Low): 신규 slot `entry_count` ↔ `daily_symbol_entries.entry_count` 이름 혼동. 대응: 테이블/키/목적/증가시점 data-model 구분, 후자 미변경(REQ-002 AC-3 회귀 보존). - R-2 (Medium): closed 후보 포함으로 동시성/점유 리셋 어긋남 → 잘못된 재사용·상태 오염. 대응: advisory lock + 단일 transit 내 상태/점유/카운트 갱신, closed→pending_buy 가 기존 closed→idle 리셋 의미 재사용, 경합 회귀 테스트. - R-3 (Medium): daily_slot 컬럼 추가가 `EXPECTED_SLOT_FIELDS`/flat 순서 깨면 광범위 회귀. 대응: 모델·계약·persistence(_SLOT_COLUMNS/row index)·data-model 동일 묶음 + 계약 가드 green. ## Notes - 1차 게이트: 단위 전체 회귀 green(entry_count 추가로 인한 flat 매핑/계약 무누락). - 결정론(NFR-2): in-memory selector(entry_count→updated_at→slot_id) + PG ORDER BY 동일 키. - PG 마이그레이션/드리프트는 라이브 runtime DSN 미사용(파괴적 truncate 회피) — test DSN 자동 검증.