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:
2026-06-08 12:57:51 +09:00
co-authored by Claude Opus 4.8
parent a24ebb242e
commit aee3512383
27 changed files with 729 additions and 33 deletions
@@ -153,3 +153,45 @@
#### Validation Plan
- BAT-002 verification evidence 재참조로 충분.
### CHG-20260608-01
- Date: 2026-06-08
- Author: Justin Ko
#### Change Summary
- (change-req, dcy-011) buy intent admission 계약 변경: `portfolio_id` 필수화 + admission 시 universe(`SnapshotStore`) 에서 `symbol` resolve + universe 부재 시 `unknown_portfolio` 거부. 기존 symbol-필수/portfolio_id-optional 폐기(hard cutover, 하위호환 없음). BAT-015 에서 재구현·재검증 완료 → Implemented 유지.
#### Intent
- 정식 식별자(asset_id=portfolio_id) 기반 원장 귀속·safety 보호 범위 정합(issue #6). `_admit_buy` 에 portfolio_id_required/unknown_portfolio reject + symbol resolve(`resolve_symbol` 주입) 추가.
#### Acceptance Criteria Delta
- Added:
- buy 는 portfolio_id 필수(누락 시 `portfolio_id_required`), symbol 은 서버 resolve(`SnapshotStore`), universe 부재 시 `unknown_portfolio` 거부.
- Updated:
- 기존 admission AC 의 symbol 입력 전제 → portfolio_id 기반으로 정정.
#### Impacted Area Delta
- Modules: `trex_core/application/intents.py`(BuyIntent portfolio_id 필수+symbol resolve, IntentService.resolve_symbol), `messaging_handlers.py`(buy payload), `runtime/daemon.py`(resolver 배선)
- Docs: `docs/interface-contract.md`, `docs/runtime-flows.md`
- Tests: intent/messaging buy 테스트 portfolio_id 기반 전환
#### Delivery Trace Delta
- Batches: BAT-015
- Releases: none
#### Revalidation Impact
- Reverification Needed: yes (BAT-015 에서 완료)
- Existing Implementation Invalidated: yes (symbol-필수 admission 경로)
- Status Recommendation: Implemented (change-req → BAT-015 재구현·재검증)
- Follow-up Action: confirm-req-implemented(BAT-015) 로 Implemented 동기화.
#### Validation Plan
- BAT-015 verification: portfolio_id_required/unknown_portfolio/symbol resolve 단위 + 전체 회귀(314 passed).