# BAT-032 Implementation - Status: done - Batch: BAT-032 ## M1 — 실행 정책 계약·파싱·슬롯 저장 (REQ-068, REQ-061 CHG-05) **변경 파일** | 파일 | 내용 | |---|---| | `trex_core/domain/slot/models.py` | `Slot` dataclass 에 `timeout_sec: Optional[int]`, `slippage_pct: Optional[float]` 추가. `EXPECTED_SLOT_FIELDS` 갱신. | | `trex_core/adapters/persistence/sql/012_add_execution_policy_fields.sql` | `ALTER TABLE daily_slot ADD COLUMN IF NOT EXISTS timeout_sec INTEGER; … slippage_pct FLOAT;` | | `trex_core/domain/slot/service.py` | `transit_slot`·`_apply_transition_fields` kwargs 확장. PENDING_* 진입 시 set, HOLDING/INACTIVE/ERROR 진입 시 clear (limit_price 동일 생애주기). | | `trex_core/adapters/persistence/postgresql.py` | `_SLOT_COLUMNS`에 col 19·20 추가. `update_slot` SQL 갱신. `_row_to_slot` 인덱스 추가. | | `trex_core/application/intents.py` | `BuyIntent`·`SellIntent` 에 `timeout_sec`·`slippage_pct` 추가. `IntentService.__init__` 에 `default_order_timeout_sec`. `_admit_buy`·`_admit_sell` 에서 effective_timeout 해석. | | `trex_core/application/messaging_handlers.py` | buy/sell 핸들러에서 `_opt_int`·`_opt_float` 파싱 추가. | | `trex_core/runtime/config.py` | `DaemonInstanceConfig.default_order_timeout_sec`. | | `trex_core/runtime/daemon.py` | `IntentService` wiring 에 `default_order_timeout_sec` 전달. | ## M2 — slippage 보호 지정가 dispatch (REQ-070, REQ-013 CHG-03 partial) **변경 파일** | 파일 | 내용 | |---|---| | `trex_core/application/execution.py` | `_dispatch`: limit 계산 후 slippage 블록 추가. buy: `ceil(limit*(1+pct/100))`, sell: `floor(limit*(1-pct/100))`. `import math` 추가. | ## M3 — timeout 집행 + race 처리 (REQ-069, REQ-013 CHG-03 partial) **변경 파일** | 파일 | 내용 | |---|---| | `trex_core/application/execution.py` | `ExecutionResult.timeout_cancelled` 추가. `_poll` else branch에 `_try_timeout_cancel` 추가. `_try_timeout_cancel` 구현: `slot.updated_at` proxy로 경과 체크 → `cancel_order` best-effort → `r.timeout_cancelled += 1`. | ## M4 — 운영자 cancel 백스톱 (REQ-071) **변경 파일** | 파일 | 내용 | |---|---| | `trex_core/application/execution.py` | `cancel_pending_slot(slot_id)` 메서드: PENDING_* slot → `cancel_order` 송신 → "ok"/"not_pending"/"slot_not_found"/"not_dispatched"/"cancel_failed" 반환. 슬롯 전이 없음 (단일 writer 보존). | | `trex_core/application/messaging_handlers.py` | `make_control_rpc_handler` 에 `cancel_pending_fn` 파라미터. `cancel_pending` 액션 라우팅. `_handle_cancel_pending` 구현. | | `trex_core/runtime/cli.py` | `cancel ` 서브커맨드. `_cmd_cancel`. `_add_intent_guards` (--yes/--dry-run/--live). control RPC 경유. | | `trex_core/runtime/daemon.py` | `make_control_rpc_handler(cancel_pending_fn=self.execution.cancel_pending_slot)` 배선. | ## M5 — baseline 문서 정합 (REQ-072) **변경 파일** | 파일 | 내용 | |---|---| | `docs/interface-contract.md` | buy/sell payload에 `timeout_sec`·`slippage_pct` 필드 기술. 하위 호환 주석 추가. cancel CLI 참조. | | `docs/runtime-flows.md` | dispatch 스텝: slippage 지정가 주석. poll 스텝: timeout 자동 취소 흐름. 실행 정책 생애주기. "운영자 cancel 백스톱" 섹션 추가. | ## 설계 결정 근거 (design.md 요약) - **D1**: `timeout_sec`/`slippage_pct` 를 slot 컬럼으로 저장 — `limit_price` 와 동일 생애주기(PENDING 진입 시 set, 탈출 시 clear). - **D2**: `slot.updated_at` 을 dispatch 시각 proxy로 사용 — 기존 stale watchdog(REQ-014)과 동일 방법, 별도 컬럼 불필요. - **D3**: `cancel_order` 송신만, 즉시 롤백 없음 — cancel-fill race 안전. 다음 poll의 `is_terminal_reject`/`is_partial_cancel` 경로 재사용. - **D4**: cancel CLI → control RPC → `ExecutionService.cancel_pending_slot` — 단일 writer 불변식(A) 보존.