feat(rel-007): dcy-025/024 + BAT-035/036 — slots.req 즉시 교체 + safety_sell_enabled

BAT-035 (dcy-025): trex.snapshot.req → trex.slots.req 즉시 교체
- topology: SNAPSHOT_REQ_QUEUE 제거, SLOTS_REQ_QUEUE = "trex.slots.req" 추가
- portfolio.py: View/build_snapshot_envelope/SnapshotEnvelope/_asset_to_dict 제거;
  slot_to_dict 시그니처 확장(snapshot_store/watchdog_store/pause_store/watchdog_timeout_sec)
  — asset_quantity(hub)/cash_balance/cash_estimated/warned/watchdog{}/paused 병합 (REQ-074)
- messaging_handlers.py: make_snapshot_rpc_handler 제거, make_slots_rpc_handler 추가
  — filter(all/inactive/pending/holding/error) + spy(bool) 처리; strategy 필드 제외 (REQ-073/074)
- daemon.py: _snapshot_rpc_loop → _slots_rpc_loop, make_slots_rpc_handler 연결
- cli.py: universe/slots → slots_queue + spy=True + server-side filter; buyable→inactive 매핑 (REQ-063)
- rabbitmq.py: snapshot_queue → slots_queue
- docs: interface-contract.md + runtime-flows.md slots.req 계약으로 업데이트 (REQ-075)
- REQ-028: Implemented → Deprecated (코드 삭제 완료)
- 테스트: test_snapshot_handler/selection/rpc_watchdog/messaging_snapshot_consumer 삭제;
  test_slots_handler.py(신규, 13 cases), test_killswitch_masking_resume 재작성,
  test_ledger_option_d._apply_cash_estimate → slots handler 경유, test_topology/cli_operator 갱신

BAT-036 (dcy-024): per-instance safety_sell_enabled 플래그
- config.py: DaemonInstanceConfig + DaemonConfig 에 safety_sell_enabled: bool = True 추가;
  from_toml 파싱, from_config 전파
- daemon.py: start() workers 조건부 — safety_sell_enabled=false 시 trex-safety-sell 미기동 + WARNING
- tests: test_instance_config.py 에 safety_sell_enabled 파싱 3개 케이스 추가

REQ: 073/074/075/021/034/063/048/005 Approved → Implemented

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 14:45:45 +09:00
co-authored by Claude Opus 4.8
parent fb05a73130
commit f0ad37747b
44 changed files with 1963 additions and 1189 deletions
@@ -1,6 +1,7 @@
# req-028: 종목 스냅샷 read 메시지 계약 + envelope + degraded 신호
- Status: Implemented
- Status: Deprecated
- Deprecated-By: REQ-073, REQ-074 (BAT-035, dcy-025, 2026-06-11)
- Type: Interface
- Priority: High
- Owner: project maintainers
@@ -256,3 +257,41 @@
- Author: Justin Ko
- Type: status
- Summary: Approved → Implemented (confirm-req-implemented). 근거: BAT-034(release-candidate) verification — allocated_capital 전 경로 제거(도메인/intent/영속/snapshot/CLI), 마이그레이션 013 테스트 DSN 멱등 round-trip + 컬럼 부재 확인, 전체 428 passed + PG 게이트 21 passed + ruff clean, grep 전수 0건. Blocking Issues 없음.
### CHG-20260611-01
- Date: 2026-06-11
- Author: Justin Ko
#### Change Summary
- (change-req, dcy-025) 본 REQ 가 소유한 snapshot read 계약(`trex.snapshot.req` 요청 view/strategy_key, 응답 envelope `assets[]`/`available_slots`/`watchdog[]`/degraded)이 **폐기 예정** — `trex.slots.req`(REQ-073) + 슬롯 단일 행 스키마(REQ-074)로 대체된다(즉시 교체, dcy-025 OQ-1). degraded/reason/message health 신호 의미는 REQ-073 으로 승계. 현재 코드는 불변이므로 Implemented 유지(keep-current, REQ-005 CHG-20260610-01 선례), dcy-025 delivery 배치에서 표면 제거와 함께 **Deprecated** 전환.
#### Intent
- snapshot→slots 표면 교체의 추적성 forward-link.
#### Acceptance Criteria Delta
- Updated: 없음(dcy-025 delivery 배치에서 본 REQ 의 envelope AC 폐기)
#### Impacted Area Delta
- Docs: dcy-025, REQ-073/074/075
- Modules: (예정) messaging_handlers.py snapshot 핸들러·portfolio.py envelope 빌더 제거/대체
#### Delivery Trace Delta
- Batches: (예정) dcy-025 delivery 배치
- Releases: none
#### Revalidation Impact
- Reverification Needed: no (현 시점 — 코드 불변)
- Existing Implementation Invalidated: no (배치 구현 시점에 무효화·Deprecated 전환)
- Status Recommendation: keep-current
- Follow-up Action: dcy-025 배치에서 표면 제거 + 본 REQ Deprecated 전환.
#### Validation Plan
- dcy-025 배치 verification 으로 대체(snapshot 표면 부재 + slots 표면 계약 검증).
@@ -191,3 +191,46 @@
#### Validation Plan
- BAT-021: 워치독 만료 holding 슬롯의 expired/last_seen 노출 단위.
### CHG-20260611-01
- Date: 2026-06-11
- Author: Justin Ko
#### Change Summary
- (change-req, dcy-025) 워치독 갱신 트리거 표면을 `trex.snapshot.req` → **`trex.slots.req`**(REQ-073)로 정합한다. 갱신 시맨틱: 기본 조회(holding 슬롯 포함)가 `last_seen_at` 을 터치하고, **`spy=true` 면 무터치**(기존 `actor="operator"`/`touch_watchdog=false` ad-hoc 플래그의 일반화·대체). 응답 노출은 top-level `watchdog[]` 배열이 아니라 슬롯 행의 `watchdog:{expired,last_seen}`(REQ-074). 만료 판정·grace period·in-memory store 는 불변.
#### Intent
- read 표면 교체 후에도 전략 폴링=생존 신호 / 비침습 조회 구분(R-4)을 보존.
#### Acceptance Criteria Delta
- Updated:
- 워치독 갱신 트리거: `trex.snapshot.req` 처리 시 → `trex.slots.req` 기본 조회 시(holding 슬롯 last_seen 갱신).
- 비침습 조회: `actor="operator"`/`touch_watchdog=false` → `spy=true`(무터치).
- 노출: 응답 `watchdog[]` 배열 → 슬롯 행 `watchdog:{expired,last_seen}`.
- Added/Removed: none
#### Impacted Area Delta
- Modules: messaging_handlers.py(터치 분기), portfolio.py(slot_to_dict watchdog 흡수)
- Docs: docs/interface-contract.md(REQ-075)
- Tests: spy 무터치/기본 터치, 행 watchdog 필드
#### Delivery Trace Delta
- Batches: 신규 batch(REQ-073/074/075 와 동일 배치, dcy-025)
- Releases: none
#### Revalidation Impact
- Reverification Needed: yes (신규 batch 에서 갱신 AC 검증)
- Existing Implementation Invalidated: yes (snapshot 표면 기반 터치·watchdog[] 노출 evidence 가 표면 교체로 무효화)
- Status Recommendation: Implemented → Approved (batch 재구현·재검증 후 복귀)
- Follow-up Action: draft-batch → 구현/검증 → confirm-req-implemented
#### Validation Plan
- 신규 BAT: 기본 조회 터치/spy 무터치 단위(REQ-073 AC-4 와 공유), 행 watchdog 필드(REQ-074 AC-1), 만료·grace 회귀.
@@ -90,3 +90,46 @@
- Author: Justin Ko
- Type: status
- Summary: Approved → Implemented (confirm-req-implemented). 근거: BAT-029(+BAT-030 trading_date 키 제거·buyable=inactive 필터) — 모든 AC 가 release-candidate 배치 verification 의 evidence 와 연결됨(단위 367/PG 29/MQ 21 passed + run-the-app 자산 중심 e2e). Blocking Issues 없음.
### CHG-20260611-01
- Date: 2026-06-11
- Author: Justin Ko
#### Change Summary
- (change-req, dcy-025) 운영자 CLI(`trex-core slots`/`universe`)의 데몬 RPC 를 `trex.snapshot.req` → **`trex.slots.req`**(REQ-073)로 교체한다. 운영자 조회는 **`spy=true`** 로 발신(기존 `actor="operator"`/`touch_watchdog=false` 대체 — 비침습 유지). `--status` 필터는 새 `filter`(status 단일: all/inactive/pending/holding/error)로 매핑. 출력 행은 REQ-074 병합 스키마(asset_quantity+qty 미러+warned, cash_balance+cash_estimated, watchdog nested, paused) 사용. universe↔slots 단일 표면 의도(본 REQ Intent)는 새 표면에서 완성된다.
#### Intent
- 운영자 단일 뷰를 새 read 표면 위로 이전(비침습·필터·병합 행 유지).
#### Acceptance Criteria Delta
- Updated:
- AC-1~3 의 underlying RPC 가 `trex.slots.req` 이고, 조회는 `spy=true`(워치독 무터치)로 수행된다. `--status` → `filter` 매핑(buyable→inactive 동치 포함).
- Added:
- AC-4: `slots` 출력 행에 REQ-074 병합 필드(asset_quantity/qty/warned/cash_balance/cash_estimated/watchdog/paused)가 표시된다.
- Removed: none
#### Impacted Area Delta
- Modules: trex_core/runtime/cli.py(`_cmd_slots`/`_cmd_universe` — 새 큐·spy·filter·행 필드)
- Docs: docs/interface-contract.md CLI↔RPC 매핑(REQ-075)
- Tests: tests/runtime/test_cli_operator.py(새 payload·행 표시)
#### Delivery Trace Delta
- Batches: 신규 batch(REQ-073/074/075 와 동일 배치, dcy-025)
- Releases: none
#### Revalidation Impact
- Reverification Needed: yes (신규 batch 에서 갱신 AC 검증)
- Existing Implementation Invalidated: yes (snapshot RPC 기반 CLI evidence 가 표면 교체로 무효화)
- Status Recommendation: Implemented → Approved (batch 재구현·재검증 후 복귀)
- Follow-up Action: draft-batch → 구현/검증 → confirm-req-implemented
#### Validation Plan
- 신규 BAT: CLI payload(`trex.slots.req`/spy=true/filter 매핑) 단위 + 행 필드 표시 단위 + buyable→inactive 동치 회귀.
@@ -0,0 +1,70 @@
# req-073: 전략 read 표면 — `trex.slots.req` RPC 계약 (filter/spy, snapshot.req 즉시 교체)
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: project maintainers
## Intent
- 자산 중심 영구 슬롯 모델(dcy-020)에서 전략 read 표면을 슬롯 단일 테이블 RPC 로 재설계한다. `trex.snapshot.req`(view/assets[]/available_slots/watchdog[] 구조)를 폐기하고 `trex.slots.req` 하나로 교체해, 전략·운영자가 슬롯 테이블 하나로 universe·포지션·워치독을 읽게 한다. (dcy-025 FR-1/2/4/5/6)
## Requirement
- per-instance 큐 `trex.slots.req`(기존 큐명 규칙 — default 는 literal, 그 외 `.{instance_key}` 접미)를 신설하고 `trex.snapshot.req` 파이프라인(큐 선언·핸들러·legacy stub 경로)을 **같은 배포에서 제거**한다(즉시 교체, 과도기 없음 — 전략 모듈 lockstep cutover, dcy-025 OQ-1).
- 요청 payload: `{filter?: str, spy?: bool}`.
- `filter` 는 **status 단일 값**(상호배타) `{all, inactive, pending, holding, error}`. 미지정 시 `all`. `pending` = `pending_buy ∪ pending_sell`. `inactive` 판정 키는 슬롯 **status**(hub `asset_quantity` 아님). 파생 view(ALL/BUYABLE/HELD)와 `View` enum 은 폐기한다 — 매수 가능 목록 = `filter=inactive`.
- `spy=true` 면 워치독을 갱신하지 않는다(생존 신호 미발생 — 기존 `actor="operator"`/`touch_watchdog=false` 의 일반화, REQ-034 정합). 기본 `false`(holding 슬롯 워치독 터치).
- 응답 payload: `{slots: [...], degraded: bool, reason, message}` **만**. `assets[]`·`available_slots`·`watchdog[]` 는 응답에 포함하지 않는다(워치독은 슬롯 행에 흡수 — REQ-074). capacity 사전 확인은 제공하지 않으며 admission(`capacity_full`)이 게이트다.
- `strategy_id`/`strategy_key`/`strategy_params`/`active_strategy_id` 는 본 표면에서 제외한다(요청 필터·응답 필드 모두 없음). 인스턴스=다중 전략이나 전략↔자산 할당 모델은 portfolio-hub 주도 후속 discovery — 확정 시 strategy 필드를 additive 로 재도입한다(dcy-025 OQ-4).
## Acceptance Criteria
1. Given 기동된 데몬, When 토폴로지 선언, Then `trex.slots.req`(per-instance) 큐가 존재하고 `trex.snapshot.req` 큐·핸들러·legacy stub 경로는 존재하지 않는다.
2. Given `{filter: "inactive"}` 요청, When 처리, Then status 가 `inactive` 인 슬롯 행만 반환된다(매수 가능 목록). `{filter: "pending"}` 은 `pending_buy ∪ pending_sell`, 미지정은 전체. 잘못된 filter 값은 `all` 또는 명시 거부로 일관 처리된다.
3. Given 응답 payload, When 키 집합 검사, Then `slots`/`degraded`/`reason`/`message` 만 있고 `assets`·`available_slots`·`watchdog`·strategy 계열 키는 없다.
4. Given `spy=true` 요청, When holding 슬롯 포함 조회, Then 워치독 `last_seen_at` 이 갱신되지 않는다. Given 기본(`spy` 미지정/false) 요청, Then holding 슬롯 워치독이 갱신된다(REQ-034 시맨틱 보존).
5. Given degraded 상태(universe fetch 실패 등), When 조회, Then `degraded=true` + `reason` 이 기존 REQ-028 신호 의미대로 운반된다.
## Impacted Area
- Docs: docs/interface-contract.md(snapshot→slots 계약 — REQ-075), docs/runtime-flows.md
- Modules: trex_core/adapters/messaging/topology.py(큐명), trex_core/application/messaging_handlers.py(slots 핸들러·snapshot 핸들러 제거), trex_core/application/portfolio.py(`View` enum 폐기)
- Tests: tests/application/(slots 핸들러 filter/spy/응답 키 집합), tests/adapters/messaging/(토폴로지)
## Notes
- 즉시 교체(과도기 없음)이므로 전략 모듈(trex-orb-v1) 소비 측을 같은 전환점에 lockstep 변경해야 한다(dcy-025 R-1/NFR-3) — 배포 전 orb-v1 의 `trex.slots.req` 대응 준비 확인. dcy-020 cutover 선례와 동일하게 단일 전환점 관리.
- 행 스키마(자산·워치독·overlay 흡수, 정본 라벨)는 REQ-074 가 소유한다.
- 운영자 CLI 의 새 표면 사용은 REQ-063 change-req(CHG-20260611-01).
- 출처: dcy-025 FR-1/2/4/5/6, NFR-1(워치독 일관성)·NFR-3(cutover 안전)은 본 REQ AC/Notes 에 흡수.
## Change Log
### CHG-20260611-01
- Date: 2026-06-11
- Author: Justin Ko
#### Change Summary
- dcy-025 FR-1/2/4/5/6 로부터 최초 생성(Proposed). `trex.slots.req` RPC 계약(filter=status 단일/spy 워치독 무터치/응답 slots+health 만/strategy 제외/즉시 교체).
#### Intent
- 전략 read 표면을 슬롯 단일 테이블로 재설계 — assets/available_slots/watchdog 병렬 구조와 파생 view 폐기.
#### Acceptance Criteria Delta
- Added:
- AC-1~5 신규
- Updated/Removed: none
#### Impacted Area Delta
- Docs: interface-contract/runtime-flows
- Modules: topology/messaging_handlers/portfolio(View 폐기)
- Tests: slots 핸들러/토폴로지
#### Delivery Trace Delta
- Batches: none(승인 후 draft-batch)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no(신규)
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current(Proposed)
- Follow-up Action: confirm-req
#### Validation Plan
- 신규 batch: 토폴로지 선언/제거 단위, filter·spy·응답 키 집합 단위, 워치독 터치/무터치, degraded 신호 회귀.