docs(batch): draft-batch BAT-029 (dcy-020 BAT-γ) + FR-7 재정의(계약 키=slot_id)

사용자 결정으로 intent 계약 키를 portfolio_id → slot_id 재정의(코어 native·스냅샷
slots[] round-trip·portfolio-hub 식별 누수 방지). 매도는 이미 slot_id; 매수만 이동
(레거시 portfolio_id dual-accept, 폐기 BAT-δ).

- REQ-061 change-req(CHG-20260610-03): 계약 키 slot_id 로 body/AC 재작성
- dcy-020 FR-7 재정의 주석(2026-06-10)
- draft-batch BAT-029(REQ-061/062/063) + design 확정
  (D1=slot_id 계약, D2=reconcile 3자 확장+A=error/B·C=warning)
- batches/index BAT-029 등록

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 12:07:10 +09:00
co-authored by Claude Opus 4.8
parent 8a377e6fb3
commit e10ac519c7
8 changed files with 182 additions and 7 deletions
@@ -6,16 +6,17 @@
- Owner: project maintainers
## Intent
- 자산 중심 모델에서 매수·매도 신호를 모두 자산(portfolio_id)으로 식별하도록 intent 계약을 통일하고, 슬롯이 자산 1:1 영구이므로 `sell-by-slot_id` 노출을 폐기한다. (dcy-020 FR-7/NFR-4)
- 전략↔코어 intent 계약을 **코어 native 키인 `slot_id`** 로 통일한다(CHG-20260610-03, 사용자 결정으로 FR-7 의 portfolio_id 키를 slot_id 로 재정의). 자산 중심 영구 슬롯이라 universe 모든 자산에 슬롯이 선존재하므로 매수도 slot_id 로 지정 가능하다. 스냅샷 `slots[]` 가 계약의 1차 단위이며 portfolio_id 는 표시/자산 정체성으로 잔존(계약 키 아님). (dcy-020 FR-7 재정의/NFR-4)
## Requirement
- 매수·매도 intent 를 모두 `portfolio_id`(자산) 키로 식별한다. 매수 = 해당 자산 슬롯 활성화(`inactive→pending_buy`), 매도 = 비활성화(`holding→pending_sell`). **`sell-by-slot_id` 는 폐기**한다. 중복/무효 신호 규칙: 이미 활성(`pending_buy`/`holding`/`pending_sell`)인 자산에 매수 신호 → 멱등 거부(`already_active`); 보유 아닌 자산에 매도 신호 → 거부(`not_holding`). `intent_id` 멱등(intent_log)은 보존한다. 계약 변경은 외부 전략 모듈을 깨뜨리므로 cutover/버전 절차를 명시한다(NFR-4).
- 매수·매도 intent 를 모두 **`slot_id`** 키로 식별한다. 매수 = 그 슬롯 활성화(`inactive→pending_buy`, symbol 은 슬롯의 `portfolio_id` 로 resolve), 매도 = 비활성화(`holding→pending_sell`). 매도는 이미 slot_id 계약(불변). **매수는 기존 portfolio_id 계약에서 slot_id 로 이동하되, 외부 전략 무중단을 위해 portfolio_id 를 레거시 dual-accept**(자산 중심 모드에서 portfolio_id → `find_slot_by_portfolio` 로 슬롯 매핑); portfolio_id 매수 계약 완전 폐기는 BAT-δ. 중복/무효 신호 규칙: 이미 활성(`pending_buy`/`holding`/`pending_sell`)인 슬롯에 매수 → 멱등 거부(`already_active`); 보유(holding) 아닌 슬롯에 매도 → 거부(`not_holding`). `intent_id` 멱등(intent_log) 보존.
## Acceptance Criteria
1. Given 매도 신호, When `portfolio_id` 로 제출, Then 해당 자산 슬롯이 `pending_sell` 로 전이하고 `slot_id` 없이 처리된다.
2. Given 이미 holding 인 자산, When 매수 신호, Then `already_active` 로 멱등 거부된다.
3. Given 보유하지 않은 자산, When 매도 신호, Then `not_holding` 으로 거부된다.
4. Given 같은 `intent_id` 재전송, When 처리, Then 슬롯 중복 전이 없이 최초 결정과 동일 응답(멱등).
1. Given 매수 신호, When `slot_id` 로 제출(자산 중심 모드), Then 그 슬롯이 `inactive→pending_buy` 로 활성화되고 symbol 은 슬롯의 portfolio_id 로 resolve 된다.
2. Given 이미 활성(pending_buy/holding/pending_sell)인 슬롯, When 매수, Then `already_active` 로 멱등 거부된다.
3. Given 보유(holding) 아닌 슬롯, When 매도, Then `not_holding`(또는 not-holding 사유)로 거부된다.
4. Given 레거시 매수(`portfolio_id`), When 제출, Then `find_slot_by_portfolio` 로 슬롯에 매핑되어 동일하게 처리된다(dual-accept, 무중단).
5. Given 같은 `intent_id` 재전송, When 처리, Then 슬롯 중복 전이 없이 최초 결정과 동일 응답(멱등).
## Impacted Area
- Docs: docs/runtime-flows.md(intent 흐름), docs/interface-contract.md(메시지 계약)
@@ -85,3 +86,37 @@
#### Validation Plan
- 승인 후 batch planning 에서 본 REQ AC 를 검증 기준으로 사용.
### CHG-20260610-03
- Date: 2026-06-10
- Author: Justin Ko
#### Change Summary
- (change-req, dcy-020 FR-7 재정의 — 사용자 결정) intent 계약 키를 `portfolio_id` → **`slot_id`**(buy·sell 공통)로 재정의. 근거: trex-core 는 슬롯 기준 관리이고 스냅샷이 `slots[]` 를 단위로 주므로 코어 native 키(slot_id)로 round-trip 하는 것이 일관적이며 portfolio-hub 식별 체계의 계약 누수를 막는다. 자산 영구 슬롯이라 매수도 slot_id 로 지정 가능(슬롯 선존재). 매도는 이미 slot_id(불변); 매수만 portfolio_id→slot_id 이동(레거시 portfolio_id dual-accept, 폐기 BAT-δ). Approved 유지(사용자 재승인).
#### Intent
- 전략↔코어 계약을 슬롯 native 키로 통일.
#### Acceptance Criteria Delta
- Updated: AC 전체를 slot_id 기준으로 재작성(AC-1 매수 slot_id 활성화·symbol resolve, AC-4 portfolio_id dual-accept 추가).
- Removed: "매도 portfolio_id 제출" 전제(매도는 slot_id 유지).
#### Impacted Area Delta
- Modules: application/intents.py(BuyIntent slot_id·_admit_buy_asset_centric), 메시지 핸들러 buy 파싱, runtime/cli.py enter
- Tests: test_asset_centric_admission(slot_id), 메시지 consumer
- 연동: REQ-059(자산 admission)·REQ-007(buy intent) — buy 키 slot_id 로 정합(BAT-029).
#### Delivery Trace Delta
- Batches: BAT-029
- Releases: none
#### Revalidation Impact
- Reverification Needed: yes (BAT-029)
- Existing Implementation Invalidated: BAT-028 의 portfolio_id 매수 admission 은 dual-accept 로 흡수(레거시 경로 유지) — 무효화 아님
- Status Recommendation: keep-current (Approved, 사용자 재승인)
- Follow-up Action: BAT-029 구현. REQ-059/007 정합.
#### Validation Plan
- BAT-029: 매수 slot_id 활성화 / portfolio_id dual-accept / already_active / 매도 slot_id / 멱등 단위·통합.