dcy-019/issue #18: slot 자원을 진입 횟수 기준으로 고르게 재사용하고 idle 소진 시 closed 슬롯을 직접 재할당한다. 거버넌스는 전부 change-req(신규 REQ 없음). - 도메인(REQ-002): Slot.entry_count(기본 0) + EXPECTED_SLOT_FIELDS, 상태 머신 closed→pending_buy 신규 전이(base 8→9, ALLOWED_TRANSITIONS 14→15), _apply_transition_fields closed→pending_buy clean-slate + →pending_buy 시 +1 - 영속화(REQ-006): 멱등 마이그레이션 008(entry_count), flat 매핑, find_allocatable_slot(idle∪closed, entry_count→updated_at→slot_id) + in-memory 동등 - admission(REQ-007): _admit_buy find_idle_slot→find_allocatable_slot + from_state=slot.status - 테스트(REQ-003): 전이 카운트/계약 가드 정합 + test_slot_entry_count.py / test_buy_admission_reallocation.py - 문서(REQ-009): data-model.md / runtime-flows.md 정합 - 기존 daily_symbol_entries(symbol-scoped) 분리·미변경 BAT-025(release-candidate) delivery + change-req REQ-002/003/006/007/009(CHG-20260609-01). REL-005(confirmed, app-service): BAT-024+BAT-025 묶음. operator-facing run-the-app 스모크로 enter --forced-close-at(BAT-024)·closed 재할당(BAT-025) 실 데몬 검증 (실 PG 마이그레이션 008 round-trip 포함). 검증: 단위 366 passed / 35 skipped(KIS sandbox 1건 deselect — live .env 환경 의존), ruff clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
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_fieldsclean-slate + entry_count +1. - REQ-003 (Testing, change-req): 전이 카운트(14→15)·필드셋 계약 가드 정합 + entry_count/reallocation 신규 단위 테스트.
- REQ-006 (Data, change-req): 멱등 마이그레이션 008 + flat slot 매핑 +
find_allocatable_slotselector. - REQ-007 (Interface, change-req):
_admit_buyfind_idle_slot→find_allocatable_slot + from_state=slot.status. - REQ-009 (Documentation, change-req): data-model/runtime-flows baseline 정합.
Delivery Plan
- REQ-002 도메인:
models.pySlot.entry_count(기본 0)+EXPECTED_SLOT_FIELDS;state.py_BASE_TRANSITIONS에closed→pending_buy;service.py_apply_transition_fieldsclosed→pending_buy clean-slate 점유 초기화 + 모든→pending_buy시entry_count+1. - 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.pyProtocol +in_memory_repository.py동등. - REQ-007 admission:
intents.py_admit_buyselector 전환 + from_state=slot.status(closed 후보 직접 재할당). - 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). - REQ-009 문서:
data-model.md(entry_count 필드/lifecycle/state rules),runtime-flows.md(admission selector/transit_slot entry_count step). - 단위 회귀 + 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
- M1 — REQ-002 도메인(field/transition/service) + 전이·계약 가드 green
- M2 — REQ-006 마이그레이션 008 + persistence 매핑 + selector + in-memory 동등
- M3 — REQ-007
_admit_buy일반화 + reallocation 단위 green - M4 — REQ-003 신규 단위 테스트 + REQ-009 문서 정합
- 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 자동 검증.