AC-0023: filter C-case quantity mismatch slots from strategy RPC, fail-closed on warn_store failure, symbol-aggregate verify clear

Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-08-25 13:17:06 +00:00
committed by GitHub
co-authored by genichin
parent d9205fe151
commit 1179bdfe23
8 changed files with 666 additions and 13 deletions
+16 -9
View File
@@ -648,31 +648,38 @@ def verify_slot_reconcile(
}
# Re-run the C-case check: hub qty vs broker qty for this symbol.
# AC-0023: use symbol-level aggregate across all portfolios (not single portfolio).
sym = slot.symbol or ""
broker_qty_map: dict[str, int] = {
item.symbol: int(item.hldg_qty) for item in broker.get_balance()
}
broker_qty = broker_qty_map.get(sym, 0)
# Hub qty: sum asset_quantity for this portfolio_id from snapshot.
# Hub qty: sum asset_quantity for ALL portfolios with this symbol in the snapshot.
hub_qty: int = 0
snap = store.get(portfolio_id)
if snap is not None:
hub_qty = int(snap.item.asset_quantity)
for a in store.list_assets():
if a.item.symbol == sym:
hub_qty += int(a.item.asset_quantity)
match = hub_qty == broker_qty
if match:
# AC-0023: clear C-case warnings for ALL holding slots with this symbol.
cleared_slots: list[str] = []
try:
warn_store.clear_warned(slot_id_str)
store.set_warning(portfolio_id, False)
for s in slot_repo.list_holding_slots(instance_key):
if s.symbol == sym:
sid_str = str(s.slot_id)
warn_store.clear_warned(sid_str)
store.set_warning(s.portfolio_id, False)
cleared_slots.append(sid_str)
_log.info(
"verify: reconcile-warning cleared (C-case resolved) "
"slot=%s portfolio_id=%s symbol=%s hub_qty=%d broker_qty=%d",
slot_id_str, portfolio_id, sym, hub_qty, broker_qty,
"symbol=%s hub_qty=%d broker_qty=%d cleared_slots=%s",
sym, hub_qty, broker_qty, cleared_slots,
)
except Exception: # noqa: BLE001
_log.exception("verify: failed to clear_warned for slot=%s", slot_id_str)
_log.exception("verify: failed to clear_warned for symbol=%s", sym)
return {
"portfolio_id": portfolio_id,
"slot_id": slot_id_str,