docs(req): dcy-020 confirm + 추가 사양(FR-6~8/NFR-4~5/OQ-8) + draft-req REQ-056~065
dcy-020(자산 중심 영구 슬롯 모델) Requirements phase. - 추가 사양: FR-6(상태머신 재정의), FR-7(intent 자산 키), FR-8(운영자 단일뷰), NFR-4(전략 계약 호환), NFR-5(불일치 감지 주기), OQ-8(over-cap=신규 차단·기존 유지), dcy-019 산출물 제거 명시. review-discovery 정리 반영. - confirm-discovery: 상태 draft→confirmed, Handoff 승인, Ready=true, Confirmed By=Justin Ko, 2026-06-10. index 행 confirmed. - draft-req: 신규 REQ-056~065(전부 Proposed) 생성 - 056 영구 슬롯 스키마 / 057 상태머신+인스턴스 lock / 058 universe reconcile - 059 capacity·admission / 060 max_active_slots TOML / 061 intent 자산 키 - 062 수량 hub 정본+불일치 해소 / 063 slots 단일뷰 / 064 cutover / 065 baseline - srs/index Next ID→066, Register 10행, Recent Change Log 갱신 - dcy-020 생성된 REQ 참조 갱신 기존 REQ-002/003/005/006/007/048 폐기·재정의 change-req 는 후속(문서 단계). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# req-057: 자산 영구 슬롯 상태머신 재정의 + 인스턴스 스코프 advisory lock
|
||||
|
||||
- Status: Proposed
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: project maintainers
|
||||
|
||||
## Intent
|
||||
- 영구 자산 슬롯에 맞춰 슬롯 상태머신을 재정의하고, holding 을 코어 로컬 정본으로 두며, 공유 DB 다중 인스턴스에서 단일 writer 불변식을 인스턴스 단위로 보존한다. (dcy-020 FR-6/FR-3/NFR-1)
|
||||
|
||||
## Requirement
|
||||
- 상태 집합을 `inactive → pending_buy → holding → pending_sell → inactive` (+ 모든 비-error → `error`, `error → {inactive, holding}` 운영자 resolve)로 재정의한다. 기존 `idle`·`closed` 는 영구 슬롯에서 단일 `inactive` 로 합치고 `closed→idle` 복구 전이를 제거한다. `holding`(포지션 열림)은 코어 슬롯의 로컬 정본으로 체결 시 동기 set, 매도 체결 시 동기 clear 한다(portfolio-hub `asset_quantity` 로 판단하지 않음). advisory lock 을 **인스턴스 스코프**(`pg_advisory_xact_lock(SLOT_LOCK_ID, hash(instance_key))`)로 두어 인스턴스 간 교차 직렬화를 제거한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 상태머신, When 허용 전이 집합을 확인, Then `{inactive→pending_buy, pending_buy→holding, pending_buy→inactive, holding→pending_sell, pending_sell→inactive, pending_sell→holding, *→error, error→inactive, error→holding}` 와 정확히 일치한다.
|
||||
2. Given 영구 슬롯, When 매도 체결로 종료, Then 슬롯은 `inactive` 로 돌아가고(별도 `closed`·`closed→idle` 없음) holding 로컬 플래그가 clear 된다.
|
||||
3. Given 서로 다른 instance_key 의 두 슬롯, When 동시에 전이, Then 인스턴스별 락으로 서로를 차단하지 않는다(교차 경합 없음).
|
||||
4. Given 같은 슬롯에 대한 동시 전이, When 병렬 처리, Then 인스턴스 스코프 락으로 직렬화되어 단일 writer 불변식이 유지된다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/runtime-flows.md(전이 흐름), docs/data-model.md(상태)
|
||||
- Modules: trex_core/domain/slot/state.py, trex_core/domain/slot/service.py, trex_core/domain/slot/models.py
|
||||
- Tests: tests/domain/slot/test_state.py, tests/domain/slot/test_service.py
|
||||
|
||||
## Notes
|
||||
- 기존 REQ-002(상태머신·서비스) 재정의 change-req 동반. dcy-001 의 6상태/closed→idle 모델 폐기.
|
||||
- holding 로컬 정본 근거(offline 안전·universe 누락 생존·hub 지연·capacity 원자성)는 dcy-020 FR-3.
|
||||
- 출처: dcy-020 FR-6, FR-3, NFR-1, OQ-7.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260610-01
|
||||
- Date: 2026-06-10
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
- dcy-020 FR-6/FR-3/NFR-1 로부터 최초 생성(Proposed). 상태머신 재정의(idle/closed→inactive, closed→idle 제거) + holding 로컬 정본 + 인스턴스 스코프 advisory lock.
|
||||
|
||||
#### Intent
|
||||
- 영구 자산 슬롯 상태머신·holding 로컬·인스턴스 단위 단일 writer 를 backlog 로 정규화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- 전이 집합/inactive 종료/인스턴스별 락 비교차/동일 슬롯 직렬화 4개 기준
|
||||
- Updated: 없음
|
||||
- Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: docs/runtime-flows.md, docs/data-model.md
|
||||
- Modules: domain/slot/state.py, service.py, models.py
|
||||
- Tests: test_state.py, test_service.py
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: none
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no (신규 정의; REQ-002 재정의 change-req 로 기존 폐기)
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req. REQ-002 change-req 동반.
|
||||
|
||||
#### Validation Plan
|
||||
- 전이 허용/거부 집합 + 인스턴스 락 단위테스트 green.
|
||||
@@ -0,0 +1,63 @@
|
||||
# req-059: 활성 capacity 제어 + 신호 기반 admission (FCFS·M캡·무치환·over-cap)
|
||||
|
||||
- Status: Proposed
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: project maintainers
|
||||
|
||||
## Intent
|
||||
- 익명 슬롯 배정 대신 "동시 활성(holding) 최대 M개" 정책으로 capacity 를 제어하고, 매수/매도 신호를 해당 자산 슬롯의 활성화/비활성화로 처리한다. (dcy-020 FR-2/FR-3/OQ-1/OQ-8)
|
||||
|
||||
## Requirement
|
||||
- 매수 신호는 해당 자산 슬롯을 활성화(`inactive→pending_buy`)한다. 활성(holding+pending_buy) 수 < M 이면 즉시 활성화, == M 이면 **거부(`capacity_full`)** 한다. 코어는 자리를 만들려고 기존 holding 을 **자율 청산(치환)하지 않는다**(FCFS·무치환). 동시 후보 tie-break 은 `updated_at` asc → `portfolio_id`(alpha 비사용). M 을 현재 보유 수보다 작게 바꿔 over-cap 이 되면 **신규 활성화만 차단**하고 기존 보유는 자연 종료까지 유지한다(강제 청산 없음). 마지막 슬롯 경합은 인스턴스 스코프 advisory lock + 재시도로 직렬화한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given 활성 수 < M, When 자산 매수 신호, Then 그 자산 슬롯이 `pending_buy` 로 활성화된다.
|
||||
2. Given 활성 수 == M, When 새 자산 매수 신호, Then `capacity_full` 로 거부되고 기존 holding 은 청산되지 않는다.
|
||||
3. Given 이미 활성(pending_buy/holding/pending_sell)인 자산, When 또 매수 신호, Then 멱등 거부(`already_active`)된다.
|
||||
4. Given M 을 현재 보유 수보다 작게 변경(over-cap), When 신규 매수 신호, Then 활성 수가 M 이하로 내려갈 때까지 신규만 거부되고 기존 보유는 유지된다.
|
||||
5. Given 동시 매수 신호 경합, When 병렬 처리, Then 인스턴스 스코프 락으로 직렬화되어 M 초과 활성화가 발생하지 않는다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/runtime-flows.md(admission→활성화 흐름)
|
||||
- Modules: trex_core/application/intents.py, trex_core/application/portfolio.py(capacity 개념)
|
||||
- Tests: tests/application/test_intent_concurrency.py, tests/application/test_*admission*.py
|
||||
|
||||
## Notes
|
||||
- M 값 출처는 REQ-060(per-instance TOML). 기존 REQ-007(admission) 재정의 change-req 동반(find_allocatable_slot/idle 배정 폐기).
|
||||
- 출처: dcy-020 FR-2, FR-3, OQ-1, OQ-8.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260610-01
|
||||
- Date: 2026-06-10
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
- dcy-020 FR-2/FR-3/OQ-1/OQ-8 로부터 최초 생성(Proposed). FCFS + M 캡 + capacity_full 거부 + 무치환 + over-cap(신규만 차단) + already_active.
|
||||
|
||||
#### Intent
|
||||
- 신호 기반 활성화/비활성화와 동시 활성 M 제어를 backlog 로 정규화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: 활성화/거부/already_active/over-cap/경합 직렬화 5개 기준
|
||||
- Updated: 없음
|
||||
- Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: docs/runtime-flows.md
|
||||
- Modules: application/intents.py, portfolio.py
|
||||
- Tests: test_intent_concurrency.py, admission 테스트
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: none
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req. REQ-007 재정의 change-req·REQ-060(M) 의존.
|
||||
|
||||
#### Validation Plan
|
||||
- FCFS/거부/over-cap/경합 단위·통합 테스트 green.
|
||||
@@ -0,0 +1,62 @@
|
||||
# req-061: intent 계약 자산(portfolio_id) 키 통일 + 중복/무효 규칙
|
||||
|
||||
- Status: Proposed
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: project maintainers
|
||||
|
||||
## Intent
|
||||
- 자산 중심 모델에서 매수·매도 신호를 모두 자산(portfolio_id)으로 식별하도록 intent 계약을 통일하고, 슬롯이 자산 1:1 영구이므로 `sell-by-slot_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).
|
||||
|
||||
## 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 슬롯 중복 전이 없이 최초 결정과 동일 응답(멱등).
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/runtime-flows.md(intent 흐름), docs/interface-contract.md(메시지 계약)
|
||||
- Modules: trex_core/application/intents.py, 메시지 핸들러/스키마
|
||||
- Tests: tests/application/test_messaging_intent_consumer.py, tests/application/test_*intent*.py
|
||||
|
||||
## Notes
|
||||
- 기존 REQ-007(intent API) 재정의 change-req 동반(sell-by-slot_id 폐기·자산 키 통일). NFR-4(전략 계약 호환): 외부 전략 모듈 동시 전환 또는 한시적 하위호환 — REQ/배치 cutover 에서 명시.
|
||||
- 출처: dcy-020 FR-7, NFR-4.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260610-01
|
||||
- Date: 2026-06-10
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
- dcy-020 FR-7/NFR-4 로부터 최초 생성(Proposed). intent 자산(portfolio_id) 키 통일 + sell-by-slot_id 폐기 + already_active/not_holding.
|
||||
|
||||
#### Intent
|
||||
- 매수·매도 신호를 자산 키로 통일하는 계약 변경을 backlog 정규화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: 매도 자산키/already_active/not_holding/intent_id 멱등 4개 기준
|
||||
- Updated: 없음
|
||||
- Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: docs/runtime-flows.md, docs/interface-contract.md
|
||||
- Modules: application/intents.py, 메시지 핸들러/스키마
|
||||
- Tests: test_messaging_intent_consumer.py, intent 테스트
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: none
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no (REQ-007 재정의 change-req 로 기존 폐기)
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req. NFR-4 외부 전략 계약 cutover 명시.
|
||||
|
||||
#### Validation Plan
|
||||
- 자산 키 매도/거부 규칙/멱등 단위·통합 테스트 green.
|
||||
@@ -0,0 +1,61 @@
|
||||
# req-063: 운영자 표면 단일화 — slots = 자산 포지션 단일 뷰
|
||||
|
||||
- Status: Proposed
|
||||
- Type: Interface
|
||||
- Priority: Medium
|
||||
- Owner: project maintainers
|
||||
|
||||
## Intent
|
||||
- universe(자산 리스트)와 slots(슬롯 상태)의 이중 표면(BAT-022 혼동 원인)을 해소하기 위해, 슬롯=자산 1:1 모델에서 `trex-core slots` 가 자산 포지션을 단일 뷰로 제공한다. (dcy-020 FR-8)
|
||||
|
||||
## Requirement
|
||||
- `trex-core slots` 가 자산 슬롯(슬롯=자산)을 단일 뷰로 표시한다: `portfolio_id`/symbol/status(inactive/pending_buy/holding/pending_sell/error)/holding 수량 미러/`universe_detached`(tombstone)/`retired`. universe(자산 리스트)와 slots(자산 포지션)는 같은 자산 집합 위의 view 가 되며, 데몬 RPC(스냅샷)로 통일한다(직접 DB 쓰기 없음). 운영자는 자산별 포지션·활성 여부·tombstone 여부를 한 표면에서 본다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given universe N개 자산, When `trex-core slots`, Then N개 자산 슬롯이 status·holding·tombstone 표시와 함께 단일 뷰로 출력된다.
|
||||
2. Given tombstone(universe-detached holding) 슬롯, When `slots`, Then `universe_detached` 로 구분 표시된다.
|
||||
3. Given `--status` 필터, When 조회, Then 자산 슬롯 status 로 필터된다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: docs/runtime-flows.md, docs/interface-contract.md(snapshot envelope slots[])
|
||||
- Modules: trex_core/runtime/cli.py, snapshot envelope 빌더
|
||||
- Tests: tests/application/test_messaging_snapshot_consumer.py, CLI 테스트
|
||||
|
||||
## Notes
|
||||
- 기존 REQ-032(운영자 CLI)·REQ-028/029(snapshot envelope) 와 연계 change-req. BAT-022 슬롯 가시화의 자산 중심 재정의.
|
||||
- 출처: dcy-020 FR-8.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260610-01
|
||||
- Date: 2026-06-10
|
||||
- Author: Justin Ko
|
||||
|
||||
#### Change Summary
|
||||
- dcy-020 FR-8 로부터 최초 생성(Proposed). `trex-core slots` = 자산 포지션 단일 뷰(universe↔slots 이중 표면 해소).
|
||||
|
||||
#### Intent
|
||||
- 운영 관측 단일화(자산별 포지션·활성·tombstone)를 backlog 정규화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: 단일 뷰 출력/tombstone 표시/status 필터 3개 기준
|
||||
- Updated: 없음
|
||||
- Removed: 없음
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: docs/runtime-flows.md, docs/interface-contract.md
|
||||
- Modules: runtime/cli.py, snapshot envelope 빌더
|
||||
- Tests: test_messaging_snapshot_consumer.py, CLI 테스트
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: none
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no (REQ-032/028/029 연계 change-req)
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req.
|
||||
|
||||
#### Validation Plan
|
||||
- slots 단일 뷰 출력·tombstone·필터 단위테스트 green.
|
||||
Reference in New Issue
Block a user