fix(slot-filled): 매도 체결 이벤트 NO_ROUTE 해소 — strategy_id 전이 전 캡처

INACTIVE 전이가 strategy_id를 None 초기화(REQ-057) → 라우팅키 slot_filled_sell._.{sym}
→ orb/tsl 바인딩 불일치 NO_ROUTE/DLQ. _on_filled/_on_partial_cancel에서 전이 직전
strategy_id 캡처해 emitter에 전달. wire 계약 불변(포맷 유지·값 교정). QC opus PASS, 747 passed/회귀 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
2026-06-29 09:38:45 +09:00
co-authored by Claude Opus 4.8
parent dc68e644d7
commit de97bc842d
3 changed files with 131 additions and 10 deletions
+10 -2
View File
@@ -264,10 +264,18 @@ class Daemon:
# ------------------------------------------------------------ event hook
def _make_event_emitter(self):
def emit(event_type: str, slot) -> None:
def emit(event_type: str, slot, routing_strategy_id: str | None = None) -> None:
payload = slot_transition_event_payload(slot, event_type=event_type)
# routing_strategy_id is supplied when the transition clears
# slot.strategy_id (e.g. PENDING_SELL -> INACTIVE for slot_filled_sell).
# Without this hint the routing key would use "_" and the message would
# be NO_ROUTEd to the DLQ instead of reaching the strategy queue
# (M2 REL-009 feedback / slot_filled NO_ROUTE fix).
effective_strategy_id = (
routing_strategy_id or getattr(slot, "strategy_id", None) or "_"
)
rk = topology.event_routing_key(
event_type, slot.strategy_id or "_", slot.symbol or "_",
event_type, effective_strategy_id, slot.symbol or "_",
)
try:
self.event_publisher.publish_event(rk, payload)