chore: plan for review blockers follow-up

Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-09-13 06:21:10 +00:00
committed by GitHub
co-authored by genichin
53 changed files with 3461 additions and 310 deletions
+33 -16
View File
@@ -12,8 +12,8 @@ from __future__ import annotations
import logging
import os
import threading
from datetime import date, datetime, time, timedelta, timezone
from typing import Callable, Optional
from collections.abc import Callable
from datetime import UTC, date, datetime, time, timedelta, timezone
from trex_core.application.alarm_emitter import AlarmEmitter
from trex_core.application.balance_health import BalanceHealthTracker
@@ -27,6 +27,7 @@ from trex_core.application.portfolio import (
ReconcileWarningStore,
SnapshotStore,
TradingContext,
UnmanagedPositionStore,
)
from trex_core.application.reconciliation import reconcile_positions
@@ -44,45 +45,51 @@ class SnapshotScheduler:
read_port: PortfolioHubReadPort,
store: SnapshotStore,
broker: BrokerPort,
core_holdings_broker: BrokerPort | None = None,
schedule_kst: time = time(hour=7, minute=30),
clock: Optional[Callable[[], datetime]] = None,
clock: Callable[[], datetime] | None = None,
slot_repo=None,
slot_service=None,
instance_key: str = "default",
alarm_emitter: Optional[AlarmEmitter] = None,
warn_store: Optional[ReconcileWarningStore] = None,
notification_store: Optional[ReconcileNotificationStore] = None,
alarm_emitter: AlarmEmitter | None = None,
warn_store: ReconcileWarningStore | None = None,
notification_store: ReconcileNotificationStore | None = None,
unmanaged_position_store: UnmanagedPositionStore | None = None,
credential_fetch_enabled: bool = False,
kis_reinit_callback: Optional[Callable[[BrokerCredentialPayload], None]] = None,
credential_refresh: Optional[Callable[[], object]] = None,
kis_reinit_callback: Callable[[BrokerCredentialPayload], None] | None = None,
credential_refresh: Callable[[], object] | None = None,
) -> None:
self._read = read_port
self._store = store
self._broker = broker
self._core_holdings_broker = core_holdings_broker or broker
self._schedule_kst = schedule_kst
self._clock = clock or (lambda: datetime.now(tz=timezone.utc))
self._daemon_id: Optional[str] = None
self._last_fired_date: Optional[datetime] = None
self._clock = clock or (lambda: datetime.now(tz=UTC))
self._daemon_id: str | None = None
self._last_fired_date: datetime | None = None
# dcy-020 / REQ-058 (BAT-030): asset-centric slot reconcile after each
# universe fetch — always on when slot_repo is wired (the reconcile is
# what creates/retires the permanent asset slots).
self._slot_repo = slot_repo
self._slot_service = slot_service
self._instance_key = instance_key
self._last_universe_size: Optional[int] = None
self._last_universe_size: int | None = None
# dcy-033 / REQ-100: best-effort alarm emitter.
self._alarm_emitter = alarm_emitter
# BAT-050 / REQ-103: durable reconcile-warning store (Optional).
self._warn_store = warn_store
# req-0007 / ac-0024: durable notification deduplication store (Optional).
self._notification_store = notification_store
self._unmanaged_position_store = unmanaged_position_store
# dcy-036 / REQ-113/114/115: credential fetch opt-in + break-glass detection.
# credential_fetch_enabled=False (default) → env-only, no portfolio-hub fetch.
self._credential_fetch_enabled: bool = credential_fetch_enabled
# dcy-036 / REQ-113 AC-2 / REQ-115 AC-1: optional callback to reinitialize
# KISBroker with the fetched day-start credential. None = no reinit (paper
# broker or credential_fetch_enabled=False). Set by daemon.py assembly.
self._kis_reinit_callback: Optional[Callable[[BrokerCredentialPayload], None]] = kis_reinit_callback
self._kis_reinit_callback: Callable[[BrokerCredentialPayload], None] | None = (
kis_reinit_callback
)
# REQ-119: provider-owned refresh supersedes the legacy raw fetch hook.
self._credential_refresh = credential_refresh
# REQ-113: detect break-glass at init time (env var set by operator).
@@ -91,8 +98,8 @@ class SnapshotScheduler:
in ("1", "true", "yes")
)
# REQ-115: day-scoped credential cache. None until first successful fetch.
self._cached_credential: Optional[BrokerCredentialPayload] = None
self._credential_date: Optional[date] = None
self._cached_credential: BrokerCredentialPayload | None = None
self._credential_date: date | None = None
# REQ-114: entry gate. True = new entries allowed (default).
# credential_fetch_enabled=False keeps this always True (no gate).
self._entry_allowed: bool = True
@@ -265,7 +272,7 @@ class SnapshotScheduler:
try:
self._credential_refresh()
self._entry_allowed = True
except Exception as exc: # provider exposes only sanitized failure
except Exception as exc: # noqa: BLE001 - provider exposes only sanitized failure
_log.error("DAY_START_LOAD_FAILED: broker credential refresh failed: %s (instance=%s)",
exc.__class__.__name__, self._instance_key)
self._entry_allowed = False
@@ -336,6 +343,7 @@ class SnapshotScheduler:
try:
from trex_core.application.reconciliation import reconcile_core_holdings
# BAT-050 / REQ-103: pass warn_store for B-case durable warning.
<<<<<<< HEAD
self._run_balance_worker(
worker="core_holding_reconciliation",
stale_after_sec=24 * 60 * 60,
@@ -346,6 +354,15 @@ class SnapshotScheduler:
warn_store=self._warn_store, # BAT-050 / REQ-103
notification_store=self._notification_store, # req-0007 / ac-0024
),
=======
reconcile_core_holdings(
slot_repo=self._slot_repo, slot_service=self._slot_service,
broker=self._core_holdings_broker, instance_key=self._instance_key,
alarm_emitter=self._alarm_emitter, # dcy-033 / REQ-100
warn_store=self._warn_store, # BAT-050 / REQ-103
notification_store=self._notification_store, # req-0007 / ac-0024
unmanaged_position_store=self._unmanaged_position_store,
>>>>>>> origin/main
)
except Exception: # noqa: BLE001
_log.exception("core-holding divergence reconcile failed")