feat(alarm): trex-core 알람 emitter + trex.alerts exchange (dcy-033 BAT-049, Implemented)

AlarmEmitter(application, best-effort 비차단)+trex.alerts topic exchange 가산·격리+8 CRITICAL code 배선. 608 passed, opus QC PASS, 팀장 e2e(텔레그램 HTTP200) 통과. REQ-098~101 Implemented.

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-21 19:25:55 +09:00
co-authored by Claude Opus 4.8
parent b2165eac25
commit d4c5fcbba1
29 changed files with 1195 additions and 47 deletions
+13
View File
@@ -11,7 +11,9 @@ from __future__ import annotations
import logging
from datetime import date as date_cls
from datetime import datetime, timezone
from typing import Optional
from trex_core.application.alarm_emitter import AlarmEmitter
from trex_core.application.portfolio import GLOBAL_KILLSWITCH, KillSwitchStore
from trex_core.domain.slot import SlotRepository, SlotService
@@ -29,11 +31,14 @@ class KillSwitchService:
slot_service: SlotService,
killswitch_store: KillSwitchStore,
instance_key: str = "default",
alarm_emitter: Optional[AlarmEmitter] = None,
) -> None:
self._repo = slot_repo
self._svc = slot_service
self._store = killswitch_store
self._instance_key = instance_key # dcy-020/REQ-056: instance-scoped sweep
# dcy-033 / REQ-100: best-effort alarm emitter.
self._alarm_emitter = alarm_emitter
@staticmethod
def _trading_date(now: datetime) -> date_cls:
@@ -73,6 +78,14 @@ class KillSwitchService:
"kill-switch fired: actor=%s scope=%s portfolio_id=%s liquidated=%d",
actor, scope, portfolio_id, liquidated,
)
# dcy-033 / REQ-100: CRITICAL alarm — emergency liquidation fired.
if self._alarm_emitter is not None:
self._alarm_emitter.publish_alarm(
"kill_switch_fired",
f"긴급 청산 발동: scope={scope} liquidated={liquidated}",
fields={"scope": scope, "portfolio_id": portfolio_id, "liquidated": liquidated,
"actor": actor},
)
return liquidated
def resume(