feat(intents): dcy-011 buy intent portfolio_id 필수 계약 + ledger skip 가시화 (BAT-015)
dcy-011 전 주기 delivery. issue #6(buy 식별자 정정) + issue #11(ledger silent skip) 흡수. 거버넌스: 기존 Implemented REQ는 change-req, 신규 기능만 신규 REQ(OQ-3). - REQ-007 (change-req): buy admission portfolio_id 필수화 + SnapshotStore symbol resolve + unknown_portfolio 거부 (hard cutover, OQ-1/OQ-2) - REQ-021 (change-req): buy 메시지 payload symbol 제거 - REQ-018 (change-req): _record_ledger skip 가시화 (WARN + ledger_skipped 카운터) - REQ-055 (신규): closed↔ledger_outbox anti-join 운영 점검 find_ledger_gap_slots 코드: intents.py(BuyIntent portfolio_id 필수 + resolve_symbol 주입 + _admit_buy reject 분기), messaging_handlers.py, runtime/daemon.py(_resolve_symbol 배선), execution.py(skip WARN 로그), adapters/persistence/ops_checks.py(신규 anti-join). 검증: 단위 282 passed/32 skipped, 인프라 게이트(PG+RabbitMQ) 314 passed, ruff clean. BAT-015(standard) release-candidate. srs/index Next ID → REQ-056. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -140,7 +140,10 @@ class Daemon:
|
||||
self.slot_repo = PostgreSQLSlotRepository(config.dsn)
|
||||
self.intent_store = PostgreSQLIntentStore(config.dsn)
|
||||
self.slot_service = SlotService(self.slot_repo)
|
||||
self.intent_service = IntentService(self.slot_service, self.slot_repo, self.intent_store)
|
||||
self.intent_service = IntentService(
|
||||
self.slot_service, self.slot_repo, self.intent_store,
|
||||
resolve_symbol=self._resolve_symbol,
|
||||
)
|
||||
self.broker = _build_broker(config)
|
||||
self.outbox = PostgreSQLLedgerOutbox(config.dsn)
|
||||
self.ledger_writer = LedgerWriter(self.outbox, _build_ledger(config))
|
||||
@@ -185,6 +188,13 @@ class Daemon:
|
||||
config=config.safety_sell,
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------ buy symbol resolve
|
||||
def _resolve_symbol(self, portfolio_id: str):
|
||||
"""dcy-011 / REQ-007: resolve symbol from the universe snapshot for a
|
||||
portfolio_id at buy admission (None → unknown_portfolio reject)."""
|
||||
asset = self.snapshot_store.get(portfolio_id)
|
||||
return asset.symbol if asset is not None else None
|
||||
|
||||
# ------------------------------------------------------------ event hook
|
||||
def _make_event_emitter(self):
|
||||
def emit(event_type: str, slot) -> None:
|
||||
|
||||
Reference in New Issue
Block a user