# 0. 문서 상태 이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다. - 상태: confirmed - 문서 ID: dcy-020_20260610_asset-centric-slot-model - 이슈명: 자산 중심 슬롯 모델 재설계 — portfolio-hub universe 와 1:1 슬롯 + 활성 슬롯 개수 제어 (일반 슬롯 풀 모델 대체) - 작성 시각(KST): 2026-06-10 01:04 KST - 마지막 갱신 시각(KST): 2026-06-10 01:04 KST (OQ-1 Answered: FCFS+무치환; FR-3/FR-4 holding/수량 정본 분리 결정; OQ-5 추가: 불일치 해소 정책; OQ-3 Answered: 영구 슬롯 + trading_date 강등 + dcy-014 폐기; OQ-2 Answered: 생성 즉시·제거 soft-retire/tombstone·degrade 보류; OQ-4 Answered: 포지션 사이징 분리·토대만; OQ-5 Answered: 불일치 해소 ground truth=브로커·표면화·운영자 게이트; A-1 CONFIRMED: 자산 중심 대전제; OQ-6 추가·Answered: M=per-instance TOML; review 정리 반영(§3 시나리오·§4·§11 현행화); OQ-7 추가·Answered: 공유 DB + instance_key 스코프(UNIQUE(instance_key,portfolio_id)) + advisory lock 인스턴스 스코프화; FR-6/7/8 추가(상태머신·intent 자산키·운영자 단일뷰), NFR-4/5 추가(전략 계약 호환·불일치 감지 주기), dcy-019 산출물 제거 명시, OQ-8 추가·Answered(over-cap=신규 차단·기존 유지); confirm-discovery 승인(2026-06-10 10:00 KST, Justin Ko) → 상태 confirmed; draft-req: REQ-056~065 생성) - 대체됨: 없음 - 후속 Discovery 참조: docs/discovery/dcy-021_20260610_position-sizing-target-intent.md (OQ-4 포지션 사이징 분리 주기), docs/discovery/dcy-027_20260612_long-term-strategy-slot-operation.md (Out-of-Scope "중장기 전용 운영(issue #20)" 이월 주기) - 생성된 REQ 참조: REQ-056(영구 슬롯 스키마), REQ-057(상태머신/lock), REQ-058(universe reconcile), REQ-059(capacity/admission), REQ-060(max_active_slots TOML), REQ-061(intent 자산 키), REQ-062(수량/불일치), REQ-063(slots 단일 뷰), REQ-064(cutover), REQ-065(baseline). 기존 REQ-002/003/005/006/007/048 등은 폐기/재정의 change-req 동반(예정). # 1. 계획 상태 요약 현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다. - 연계 문서 현황: - 관련 점수 파일: 미생성 - 관련 TODO/메모: GitHub issue #1(포지션 사이징/선언형 target intent), issue #20(중장기 자산 중심 운영). 기존 dcy-001/002(슬롯 도메인·intent), dcy-005(스냅샷 universe read), dcy-014(일일 preallocation), dcy-019(slot entry_count + closed 재할당)와 직접 교차. - 해석: - 현재 모델은 **익명 슬롯 풀**(일일 N개 preallocation, 매수 신호 시 idle 슬롯을 자산에 동적 배정)이다. 운영 마찰(universe↔slots 표면 혼동 BAT-022, `no_idle_slot`/할당 경합, entry_count 재사용 정책 dcy-019)과 issue #1(포지션 사이징 자리 없음)·#20(자산 중심 다일 보유와 충돌)이 모두 이 풀 모델 전제에서 비롯된다. - 본 Discovery 는 슬롯을 **portfolio-hub universe 자산과 1:1**로 두고("슬롯=자산 포지션"), capacity gate 를 "유휴 슬롯 수"에서 "**동시 활성(holding) 최대 M개**" 정책으로 바꾸는 모델 전환을 판정한다. issue #1·#20 을 흡수하는 상위 substrate 재설계이며, 기존 dcy-001/002/014/019 의 풀 모델 전제를 재정의한다. # 2. 요구사항 판정 결과 이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다. - 판정: 신규 - 근거 - 기존 dcy 들은 모두 **익명 슬롯 풀** 전제(일일 count preallocation·idle 배정·closed 재할당) 위에 쌓였다. 자산 1:1 슬롯 + 활성 개수 제어는 슬롯의 정체성·할당·capacity 개념을 **재정의**하므로 기존 문서의 미세 조정으로 흡수되지 않는다. - issue #1(포지션 사이징)·#20(중장기) 과 교차하나, 그 둘을 따로 풀지 않고 substrate(슬롯 모델)를 바꿔 동시에 단순화하는 독립 주기다. 기존 dcy-001/002/014/019 는 입력·영향(폐기/재해석 범위)으로 참조한다. # 3. 문제점의 요약 문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다. - 현재 상태 - **익명 슬롯 풀 + 일일 count preallocation**: `preallocate_daily_slots(trading_date, count)`(`preallocation_scheduler.py`, dcy-014)가 매일 `TREX_TOTAL_SLOTS`(기본 10)개의 idle 슬롯을 생성한다. 슬롯은 특정 자산에 묶이지 않은 익명 capacity 다. - **매수 신호 시 동적 배정**: buy admission(`intents.py:_admit_buy`)이 `find_allocatable_slot`(idle∪closed, dcy-019/BAT-025)로 슬롯 1개를 잡아 portfolio_id 를 채운다. capacity gate 는 `available_slots = idle_count`(`portfolio.py`/`messaging_handlers.py`). - **universe 와 slots 가 별개 표면**: universe(자산 리스트)는 portfolio-hub `get_portfolios(daemon_id)`(`hub_read.py`, `managed_by_daemon_id` 필터)로 읽고, slots(슬롯 상태)는 별도다. 둘의 임피던스가 운영 혼동(BAT-022: `slots` 가 universe 를 슬롯으로 오인 표시)과 정합 마스킹(REQ-031: hub 수량 vs 브로커 수량 불일치 시 universe 마스킹)을 낳았다. - **포지션 사이징 자리 없음**: 상태머신(`state.py`)이 이산적(IDLE→PENDING_BUY→HOLDING→PENDING_SELL→CLOSED)이라 `HOLDING→HOLDING`(수량 변경)·부분 매도가 없다(issue #1). - **일일 리셋 vs 영구 자산**: 슬롯이 trading_date 로 일일 preallocation 되어 다일 보유 자산 모델(issue #20)과 충돌한다. - baseline 문서(`docs/project-structure.md`, `docs/runtime-flows.md`, `docs/data-model.md`)는 존재·최신이며 슬롯 풀·preallocation·admission 흐름을 기술한다 — 본 전환 시 대폭 갱신 대상. - 기대 상태 - 슬롯이 portfolio-hub universe 자산과 **1:1**로 대응되어 "슬롯=자산 포지션"이 된다. 익명 배정·할당 경합·closed 재할당 개념이 사라진다. - capacity 제어가 "**동시 활성(holding) 슬롯 최대 M개**" 정책으로 표현되어, 활성화는 FCFS(신호 도착 순)이고 M 이 차면 새 신호를 거부한다(코어 자율 치환 없음, OQ-1). 능동적 capacity 배분은 전략 선언형 target(OQ-4)으로 분리한다. - universe↔slots 표면이 합쳐져 운영 관측이 단순해진다. 다일 보유(#20)는 영구 슬롯으로 이번 주기에 실현되고, 포지션 사이징(#1)은 본 토대 위 **후속 주기**로 얹힌다(OQ-4 분리). - 이해관계자 - 문서 작성자(AI agent) — Discovery/REQ/Batch 산출물 - 리뷰어/승인자 — 슬롯 모델·capacity 정책·기존 작업 폐기 범위 승인 - 운영 담당자 — 자산별 포지션·활성 수 관측 - 전략 모듈 — 슬롯=자산이면 신호·소유 시맨틱(dcy-005 OQ-9)이 바뀜 - portfolio-hub 팀 — universe 가 슬롯 집합의 source of truth 가 됨(자산 추가/제거 동기화) - 제약사항 - 검증·출시된 풀 모델 경로(REL-001~004, BAT-001~023)와 방금 출시한 dcy-019/BAT-025(entry_count·closed 재할당)를 **재정의/폐기**해야 한다 — 회귀·이행 비용이 크다. - portfolio-hub universe 가 변동(자산 추가/제거)하므로 슬롯 생성/소멸 lifecycle 을 스냅샷 refresh 와 결합해야 한다. - 단일 writer·동시성·불변식(advisory lock, REQ-002 NFR-1)을 새 모델에서도 보존해야 한다. ## 주요 사용자 시나리오 사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다. - portfolio-hub 가 45개 자산을 제공하면 trex-core 에 45개 자산 슬롯이 생기고, 운영자는 "동시 활성 최대 M개" 만 제어한다 — 어떤 자산을 살지는 슬롯 배정이 아니라 활성 선택으로 결정된다. - 매수 전략이 자산 A 신호를 주면 A 의 슬롯이 활성화(holding)되고, 활성 수가 M 미만이면 즉시 활성화, M 이 차 있으면 거부된다(FCFS·코어 자율 치환 없음, OQ-1). 회전은 전략의 명시적 sell→buy 로 한다. - (후속 주기) 보유 중 전략이 목표 수량을 바꾸면(issue #1) 같은 자산 슬롯의 수량이 조정된다(별도 슬롯 불필요) — 본 주기는 토대만, 포지션 사이징은 분리(OQ-4). - 운영자가 `trex-core slots` 로 자산별 포지션·활성 여부를 한 표면에서 본다(universe↔slots 분리 해소). # 4. 이번에 정의할 변경 이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다. - 슬롯 정체성 재정의: 익명 풀 → **portfolio-hub universe 자산과 1:1 바인딩**(슬롯 = 자산 포지션, portfolio_id 영구 키). - 슬롯 lifecycle 재설계: 일일 count preallocation(dcy-014) → **universe 기반 슬롯 생성/소멸**(스냅샷 refresh 와 결합). idle 풀·`find_allocatable_slot`·closed 재할당(dcy-019) 폐기/대체. - 슬롯 영속성 전환(OQ-3): 일일 리셋 → **영구 슬롯**(키=`portfolio_id`, `UNIQUE`, 날짜 없음). `daily_slot.trading_date` 컬럼 드롭/재의미, trading_date 는 이벤트/원장/정책의 시간 속성으로 강등. 일일 daily_slot 행 → 자산당 영구 1행 cutover + 보유 carry-over. - capacity 제어 전환: `available_slots`(유휴 수) → "**동시 활성 holding 최대 M개**" 정책. 활성 수 == M 이면 신규 신호 거부(FCFS·무치환, OQ-1). M 값은 per-instance TOML 설정에서 읽는다(OQ-6). - 상태머신 재해석(FR-6): 익명 슬롯의 IDLE/CLOSED → 영구 슬롯의 **단일 `inactive`** 로 합침(`closed→idle` 복구 전이 제거), 집합 = `inactive→pending_buy→holding→pending_sell→inactive`(+`error`). 활성=진입, 종료=전량 청산. **HOLDING→HOLDING 수량 변경·부분 매도 미포함**(포지션 사이징 OQ-4 분리). 수량 가변 전제는 모델에 남김. - intent 계약 통일(FR-7): 매수·매도 모두 portfolio_id(자산) 키, `sell-by-slot_id` 폐기, 중복/무효 신호 멱등 거부(`already_active`/`not_holding`). - 운영자 표면 단일화(FR-8): `trex-core slots` = 자산 포지션 단일 뷰(universe↔slots 이중 표면 해소, BAT-022). - dcy-019 산출물 제거(FR-5): `find_allocatable_slot`·`closed→pending_buy` 전이·slot `entry_count` 제거(FCFS·영구 슬롯이 대체). `daily_symbol_entries` 폐기. - baseline 문서(`docs/project-structure.md`/`docs/runtime-flows.md`/`docs/data-model.md`) 전면 갱신 + 기존 dcy-001/002/014/019 와의 대체/재해석 관계 명시. ## 영향 범위 변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다. - 코드 영향: - `trex_core/domain/slot/` — 상태머신(state.py)·서비스(service.py)·모델(models.py): 슬롯 정체성·전이·capacity 개념 재정의 - `trex_core/application/preallocation_scheduler.py` — count preallocation → universe 기반 생성/소멸로 대체 - `trex_core/application/intents.py` — `find_allocatable_slot` 배정 경로 → 자산 슬롯 활성화/선택 경로 - `trex_core/application/snapshot_scheduler.py` / `portfolio.py` — universe fetch 와 슬롯 집합 동기화 결합, `available_slots`→활성 수 개념 - `trex_core/adapters/persistence/postgresql.py` + 마이그레이션 — daily_slot 스키마(자산 키·활성 플래그·`retired_at`·`instance_key`) 재설계, `UNIQUE(instance_key, portfolio_id)`; slot-scoped 테이블 전반 instance 스코프화 + 모든 쿼리에 instance 필터(OQ-7) - `trex_core/domain/slot/state.py`·`service.py` — advisory lock 인스턴스 스코프화(`(SLOT_LOCK_ID, hash(instance_key))`, NFR-1 재정의, OQ-7) - `trex_core/runtime/config.py`(`DaemonInstanceConfig`) + `config/*.toml` — 동시 활성 최대치 M 설정 키(예: `max_active_slots`) 추가(OQ-6, REQ-048 per-instance TOML 계열) - 문서 영향: - `docs/data-model.md`(daily_slot 재설계: instance_key·retired_at·entry_count 제거·trading_date 강등), `docs/runtime-flows.md`(admission→활성화 흐름·reconcile lifecycle·불일치 해소), `docs/project-structure.md`(슬롯 모델) - `trex_core/domain/slot/state.py`·`models.py` — 상태 집합 재정의(FR-6: idle/closed→inactive), `entry_count` 제거 - `trex_core/application/intents.py`·메시지 계약 — intent 자산 키 통일·sell-by-slot_id 폐기(FR-7); `trex_core/runtime/cli.py` slots 단일 뷰(FR-8) - (제거) `daily_symbol_entries` 테이블·`find_allocatable_slot`·`closed→pending_buy` 전이(dcy-019 산출물) - 운영 영향: - 슬롯 수가 universe 크기에 연동, capacity 운영이 "활성 M개" 정책으로 전환. 마이그레이션·이행 절차 필요. 기존 풀 모델 운영 가정 변경. # 5. 요구사항 목록 실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다. ## 기능 요구사항 - FR-1: 슬롯은 portfolio-hub universe 의 자산과 1:1 로 대응한다(자산 portfolio_id 가 슬롯의 **영구 키**, 날짜 없음 — OQ-3). **다중 인스턴스는 DB 를 공유하고 슬롯은 `instance_key` 로 스코프**하므로 슬롯 유일성은 **`UNIQUE(instance_key, portfolio_id)`** 이다(OQ-7). `daily_slot` 에 `instance_key` 컬럼 추가, slot-scoped 테이블 전반(slot_transition_log/intent_log/ledger_outbox/snapshot_pause/killswitch_exclusion 등)도 instance 스코프화·쿼리 필터. `daemon_id` 는 universe 파티션(get_portfolios)·감사용으로 (선택) 병행 저장하되 스코프 키는 아니며, instance_key↔daemon_id 1:1 정합을 가드한다(OQ-7). 슬롯은 **영구**이며 날 경계로 리셋되지 않고, universe 동기화(reconcile, OQ-2) 시: 신규 자산 → 슬롯 즉시 생성(비활성·멱등); 제거 자산 → **비활성이면 soft-retire(행 보존, `retired_at`/`universe_detached` 마킹, hard delete 금지)·보유 중/pending 이면 tombstone(safety-sell 유지·신규 매수 제외, 닫힌 뒤 은퇴)**. reconcile 은 스냅샷 refresh 경로(부팅+매일 07:30 KST, +운영자 on-demand)에서 단일 writer(advisory lock)로 수행. `retired_at`/`universe_detached` 는 status 와 직교한 마커. 슬롯 행의 기존 `trading_date` 컬럼은 드롭/재의미하고, trading_date 는 이벤트/원장/정책의 시간 속성으로 강등(OQ-3). 일일 preallocation(dcy-014)은 폐기하고 슬롯 생성을 universe reconcile 로 대체. - FR-2: capacity 는 "동시 활성(holding) 슬롯 최대 M개"로 제어한다. 활성화는 **FCFS(신호 도착 순)**이며 활성 수 == M 이면 새 신호를 **거부(`capacity_full`)**한다 — 코어는 자리를 만들려고 기존 holding 을 자율 청산(치환)하지 않는다(OQ-1). 도착 순서는 단일 writer 직렬화로 결정적이고, 동시 후보 tie-break 은 `updated_at` asc → `portfolio_id`(alpha 비사용). capacity 를 최고 기회에 배분하는 능동 선택이 필요하면 전략의 선언형 target(OQ-4/issue #1)으로 처리한다. **M 값은 per-instance TOML 설정(`config/*.toml`, 예: `max_active_slots`)에서 읽는다**(REQ-048 per-instance TOML 계열, OQ-6) — 인스턴스별 독립 운영. - FR-3: 매수/매도 신호는 익명 슬롯 배정이 아니라 **해당 자산 슬롯의 활성화/비활성화**로 처리한다. 동시성·단일 writer·불변식(advisory lock)을 보존한다. **holding(포지션 열림 여부)은 코어 슬롯의 로컬 정본**으로, 체결 시 동기 set·매도 체결 시 동기 clear 한다 — portfolio-hub `asset_quantity` 로 판단하지 않는다. 근거: (1) 자율 안전 매도(forced_close/stop_loss/take_profit/market_close/watchdog/kill-switch)는 portfolio-hub 불가 시에도 독립 동작해야 하므로(REQ-024) 보유 사실을 코어 durable 상태에서 알아야 한다; (2) universe 에서 자산이 빠지면 `get_portfolios` 에서 사라져 `asset_quantity` 신호가 증발하지만 로컬 holding 은 생존(OQ-2 고아 포지션 방지); (3) hub 수량은 ledger outbox 비동기 전파(dcy-015)라 지연되므로 안전 판단의 primary 신호로 부적합; (4) capacity(M개, FR-2) 카운트의 원자성은 단일 writer 슬롯 상태라야 보장. (사용자 결정 2026-06-10) - FR-4: 보유 **수량(asset_quantity)의 정본은 portfolio-hub**이며, 슬롯은 수량을 정본 소유하지 않고 **로컬 best-effort 미러**(option D write-back `*_after`·추정 오버레이, BAT-023)로만 둔다. 실제 청산 시 매도 수량은 **브로커 잔고(`BrokerPort.get_balance().hldg_qty`)를 정본**으로 조회한다 → 로컬 미러가 stale 해도 청산 정확. 브로커 잔고는 포지션 존재·수량 불일치의 **reconcile ground truth** 이기도 하다(OQ-5). 즉 "포지션 열림(boolean)=코어 로컬, 수량=hub 정본+로컬 미러"로 분리. (issue #1 연계) 활성 슬롯의 보유 **수량 변경(포지션 사이징)** 은 본 주기에서 **분리(OQ-4 Out of Scope)** — 단 수량 가변 전제는 모델에 남긴다(토대 가드). 슬롯이 `qty`/`avg_price` 를 정본 소유하던 풀 모델(reconcile_positions/REQ-031 warning, option D write-back 의 drift 원인)은 본 분리로 정리한다. (사용자 결정 2026-06-10) - FR-5: `docs/data-model.md`·`docs/runtime-flows.md`·`docs/project-structure.md` 를 새 모델로 갱신하고, dcy-001/002/014/019 의 폐기/재해석 범위를 명시한다. **dcy-019 산출물 구체 처분**: `find_allocatable_slot` selector·`closed→pending_buy` 전이·slot `entry_count` 필드는 FCFS·영구 슬롯 전환으로 **제거**(슬롯 회전 분석이 필요하면 `slot_transition_log` 로 도출, 슬롯 컬럼 아님). `daily_symbol_entries`(symbol-scoped 재진입 카운터)도 자산 중심 모델에서 무의미 → 폐기(별도 트랙과 합류). - FR-6: **슬롯 상태머신을 자산 영구 슬롯에 맞게 재정의**한다. 기존 `idle`(매수 전)·`closed`(매도 후)는 영구 슬롯에서 **단일 `inactive`(포지션 없음)** 로 합쳐지고(dcy-001 `closed→idle` 복구 전이 제거), 상태 집합 = `inactive → pending_buy → holding → pending_sell → inactive`(+ 모든 비-error → `error`, `error → {inactive, holding}` 운영자 resolve). `retired_at`/`universe_detached`(OQ-2)·`instance_key`(OQ-7)는 status 와 **직교한 속성**으로 둔다. 활성=진입, 종료=전량 청산(HOLDING→HOLDING·부분 매도 미포함, OQ-4). - FR-7: **intent 계약을 슬롯 native 키(`slot_id`)로 통일**한다(2026-06-10 재정의 — 아래 주). 매수·매도 모두 `slot_id` 로 식별하고 스냅샷 `slots[]` 가 계약 1차 단위; portfolio_id 는 표시/자산 정체성으로 잔존(계약 키 아님). 매수 = 그 슬롯 활성화(`inactive→pending_buy`, symbol 은 슬롯 portfolio_id 로 resolve), 매도 = 비활성화(`holding→pending_sell`). **중복/무효 규칙**: 이미 활성(`pending_buy`/`holding`/`pending_sell`)인 슬롯에 매수 → `already_active`; 보유(holding) 아닌 슬롯에 매도 → `not_holding`. intent_id 멱등 보존. - **[재정의 2026-06-10, 사용자 결정 / REQ-061 CHG-20260610-03]** 최초 FR-7 은 `portfolio_id` 키 통일(+sell-by-slot_id 폐기)였으나, trex-core 가 슬롯 기준 관리이고 스냅샷이 `slots[]` 를 단위로 주므로 **코어 native 키 `slot_id` 로 통일**하는 것이 일관적이고 portfolio-hub 식별 체계의 계약 누수를 막는다. 자산 영구 슬롯이라 매수도 slot_id 로 지정 가능(슬롯 선존재). 매도는 이미 slot_id(불변); 매수만 portfolio_id→slot_id 이동(레거시 portfolio_id dual-accept, 폐기 BAT-δ). slot_id 는 계약 키이자 내부 PK 로 잔존(제거 아님). - FR-8: **운영자 표면 단일화** — `trex-core slots` 가 자산 포지션(슬롯=자산, status·holding·수량 미러·`universe_detached`/`retired`)을 **단일 뷰**로 보여준다. universe↔slots 이중 표면(BAT-022 혼동 원인) 해소. universe(자산 리스트)와 slots(자산 포지션)가 같은 자산 집합 위 view 가 된다. ## 비기능 요구사항 성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다. - NFR-1: 동시성·일관성 — 슬롯 활성화/수량 변경은 advisory lock/단일 트랜잭션으로 경합 없이 처리(REQ-002 NFR-1 계승). **공유 DB 다중 인스턴스에서 단일 writer 불변식은 인스턴스 단위로 재정의**한다: advisory lock 을 인스턴스 스코프화(예: `pg_advisory_xact_lock(SLOT_LOCK_ID, hash(instance_key))`)해 인스턴스 간 교차 경합(한 인스턴스 전이가 타 인스턴스를 막음)을 제거한다(OQ-7). - NFR-2: 이행 안전 — 기존 풀 모델 데이터/운영에서 새 모델로의 마이그레이션이 검증된 매수/매도 경로(REL-001~004)를 회귀시키지 않거나, 명확한 cutover 절차를 갖는다. - NFR-3: universe 결합 견고성 — portfolio-hub 불가/degraded 시 슬롯 생성·은퇴를 **전부 보류**하고 마지막 집합을 유지한다(`SnapshotStore` degraded 신호 재사용). fetch 성공이라도 universe 가 N→0/급격 대량 감소면 글리치로 의심해 **mass-retire 보류 + 경고**(정상 단건 제거와 구분). 보유 중 자산은 universe 누락에도 tombstone 으로 보호되어 포지션을 잃지 않는다(OQ-2). 코어 holding↔브로커/hub 의 **비정상 불일치**는 브로커를 ground truth 로 감지(REQ-031 reconcile 확장)하되 조용한 자동 교정 없이 warning/`error`+운영자로 표면화하고, 실주문 발생은 운영자 게이트로 둔다(OQ-5). - NFR-4: 전략 계약 호환 — intent 계약 변경(FR-7: 자산 키 통일, `sell-by-slot_id` 폐기)·snapshot envelope 의미 변경(FR-8)이 외부 전략 모듈을 깨뜨리므로, **계약 버전/cutover 절차**를 REQ/배치에서 명시한다(전략 모듈 동시 전환 또는 한시적 하위호환). 슬롯 선택은 여전히 core 책임(전략은 자산 신호만, A-3 계승). - NFR-5: 불일치 감지 주기 — 코어 holding↔브로커 비정상 불일치(OQ-5 Case B, 미보호 고아 포지션)는 안전 민감이므로, 감지 reconcile 은 일일 universe refresh 와 **분리해 더 자주** 수행 가능해야 한다(브로커 잔고+슬롯 상태만 필요, 전체 universe fetch 불필요). 구체 주기는 설계 tuning. ## 범위 경계 이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다. - In Scope - 슬롯=자산 1:1 영구 모델 + 활성 개수 제어(M, FCFS+무치환) 정책 정의 - 슬롯 lifecycle 의 universe 동기화(생성/soft-retire/tombstone) 설계 - 기존 풀 모델(일일 preallocation/idle 배정/closed 재할당) 폐기·재해석 + 일일행→영구행 cutover 범위 산정 - holding=코어 로컬·수량=hub 정본+미러 분리(FR-3/FR-4) - baseline 문서 재설계 요구 - 토대 가드: 수량 가변 전제 유지(고정 가정 금지) + "활성=진입/종료=전량 청산" 상태 경계 고정(후속 사이징 얹힘 대비) - Out of Scope - **포지션 사이징(활성 슬롯 보유 수량 변경)·선언형 target intent(issue #1) — 분리(OQ-4), 별도 후속 Discovery.** 본 주기는 HOLDING→HOLDING 수량 변경·부분 매도를 구현하지 않는다. - 중장기 전용 운영(issue #20)의 전체 — 본 모델은 토대만 제공(다일 보유는 영구 슬롯으로 실현) - 코어 holding↔broker/hub 비정상 불일치 해소 정책 — OQ-5(잔여 Open) - 전략 모듈 내부 구현(외부 repo) # 6. 리스크/가정 목록 불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다. ## 리스크 - R-1 (High): 검증·출시된 풀 모델(REL-001~004, 특히 방금 출시한 dcy-019/BAT-025)을 폐기/재정의 — 광범위 회귀·재작업·이행 위험. OQ-3(영구 슬롯) 확정으로 **일일 daily_slot 행 → 자산당 영구 1행 cutover + 현재 보유 포지션 carry-over** 가 본 주기 최대 작업으로 구체화됨. 일일 preallocation(dcy-014) 폐기, `daily_slot.trading_date` 스키마 변경 동반. - 완화 방안: 영향 분석으로 폐기 범위를 명시하고, cutover/마이그레이션(일일행→영구행, 보유 carry-over, **기존 데이터 instance_key 태깅 + slot-scoped 테이블 instance 스코프화**, OQ-7) 절차와 회귀 테스트를 REQ/배치 단계에서 우선 설계. trading_date KST 계산(REQ-005)은 일일 회계 경계용으로 존속(부분 재해석). 단계적 전환(읽기 정합 → 모델 전환) 검토. - R-2 (완화): universe 변동에 따른 슬롯 생성/소멸이 보유 포지션·진행 중 주문과 충돌(예: 보유 중 자산이 universe 에서 빠짐). - 완화 방안: OQ-2 확정 — 보유 중/pending 슬롯은 **tombstone**(은퇴 금지, safety-sell 유지, 닫힌 뒤 은퇴), 비활성만 soft-retire(행 보존), degrade·대량소멸 시 보류(NFR-3). 잔여는 비정상 divergence(OQ-5)로 분리. - R-3 (해소): "활성 M개" 정책의 선택/치환 규칙이 모호하면 비결정적·불공정 활성화. - 완화 방안: OQ-1 을 FCFS+무치환(단일 writer 직렬화로 도착 순서 결정적, tie-break `updated_at`→`portfolio_id`)으로 확정 — 치환 분기 자체를 제거해 모호성 해소. 재현성은 테스트로 보장. ## 가정 아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다. - A-1: 제품 방향이 "알려진 universe 자산의 포지션 관리 + 동시 보유 수 제어"(자산 중심)이며, 익명 capacity 풀(기회주의적 자본 배분)이 아니다. — **CONFIRMED (2026-06-10, 사용자 확정)**. 모델 전환의 대전제 성립 → OQ-1~5 결정의 기반. - A-2: portfolio-hub universe(`get_portfolios`, `managed_by_daemon_id` 필터)가 슬롯 집합의 source of truth 로 적절하다. - A-3: 단일 writer·advisory lock 불변식은 새 모델에서도 유지 가능하다. ## 오픈 질문 답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다. - OQ-1: 활성 후보가 "최대 M개"를 초과할 때 활성 자산 선택/치환 규칙은 무엇인가(우선순위·tie-break·기존 보유 우선 등). - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **FCFS(신호 도착 순) + 가득 차면 거부, 코어 자율 치환(eviction) 없음.** 활성 수 < M 이면 신호 온 자산 즉시 활성화, 활성 수 == M 이면 새 신호 거부(`capacity_full`) — 자리를 만들려고 기존 holding 을 코어가 임의 청산하지 않는다. 도착 순서는 단일 writer + advisory lock 직렬화(intent_log 시퀀스)로 이미 결정적이며, 동시 후보가 실제로 생기는 경로(재기동·정합)의 tie-break 은 alpha 가 아닌 내재적 결정 키(`updated_at` asc → `portfolio_id`)로 한다. - 근거: (1) "코어는 집행, 전략은 alpha" 분리 보존 — 어떤 자산이 더 좋은지(살지/뺄지)는 전략 책임이며, 코어가 score 로 후보를 줄 세우면 alpha 판단을 흡수한다(dcy-019 A-3 계승). (2) 치환=자율 청산이라 사용자 채택 "코어 자율 청산 안 함" 원칙(issue #15)과 충돌 — 회전이 필요하면 전략이 명시적 sell→buy 로 수행(감사 로그에 의도 잔존). (3) 결정성(NFR-1/R-3)이 직렬화로 공짜로 따라온다. - 트레이드오프 & 연동: FCFS 는 확신 낮은 이른 신호가 슬롯을 점유해 더 좋은 후속 신호를 막을 수 있다. "M개 capacity 를 최고 기회에 배분"이 필요하면 그것은 **전략이 'M개 목표 포트폴리오'를 선언**하고 코어가 reconcile 하는 모델(OQ-4 / issue #1)로 처리한다 — 그 경우 선택 규칙은 전략 선언으로 이동하고 OQ-1 은 "target 이 M 초과면 선언 검증 단계에서 거부"가 된다. 본 결정은 OQ-4 분리(토대만) 전제에서의 단순 규칙이며, 선언형 target 채택 시 자연 확장된다. - 반영: FR-2, R-3, §3 기대 상태, §10 DECIDE. - OQ-2: universe 변동 시 슬롯 lifecycle — 신규 자산 슬롯 생성 시점, 제거 자산(특히 보유 중) 슬롯의 소멸/청산/보류 규칙, 스냅샷 refresh 와의 결합 방식. - 상태: Answered (2026-06-10, 사용자 결정) - 결정 (영구 슬롯 OQ-3·holding 로컬 FR-3 전제): - **생성**: universe 신규 자산 → 영구 슬롯 즉시 생성(비활성). `get_portfolios` reconcile 경로에서 수행, `UNIQUE(portfolio_id)` 멱등(있으면 no-op). fetch 성공 시에만. - **제거 — 비활성**(holding 아님 + pending 주문 없음): **soft-retire**(행 보존, `retired_at`/`universe_detached` 마킹). **hard delete 금지** — `slot_transition_log` 이력 보존 + 같은 자산 재추가 시 동일 슬롯 재활성화(영구 portfolio_id 키). - **제거 — 보유 중/ pending 진행 중**: **은퇴 금지, tombstone**. 슬롯 유지 + safety-sell/watchdog 계속 동작(FR-3), universe-detached 로 마킹해 **신규 매수 후보 제외**하되 기존 포지션은 보호·매도 가능. 슬롯이 닫힌(매도 체결) **후 은퇴**. 코어 자동 청산 안 함(issue #15). - **cadence**: 기존 스냅샷 refresh(`run_once()` 의 `store.swap` 직후, 부팅 + 매일 07:30 KST)에 reconcile 을 얹는다 — 별도 빠른 루프 불필요(영구 슬롯이라 제거 지연이 tombstone 으로 안전). 즉시성 필요 시 운영자 on-demand reconcile(CLI) 허용. - **degrade + 대량소멸 가드**(NFR-3): portfolio-hub 불가/degraded → 생성·은퇴 전부 보류, 마지막 집합 유지. fetch 성공이라도 universe 가 N→0/급격 대량 감소면 글리치 의심 → mass-retire 보류 + 경고(정상 단건 제거와 구분). - **단일 writer**: 생성/은퇴 쓰기도 전이와 같은 advisory lock 경로(스냅샷 스레드가 repo 통해). - **새 마커**: `retired_at`(또는 `universe_detached` boolean) — 포지션 lifecycle(status)과 **직교**(status enum 에 'retired' 넣지 않음). "보유 중 + universe-detached" 조합 표현용. - **capacity 상호작용**: tombstone-holding 슬롯은 실포지션이므로 M 카운트 포함(닫힐 때까지), 단 재매수 불가. - 반영: FR-1, NFR-3, §4, R-2, §10 DECIDE. OQ-5(비정상 divergence)와 경계 구분 — universe-detached holding 은 예상된 정상 케이스(tombstone), 코어-holding↔broker-0 같은 비정상은 OQ-5(error/operator). - OQ-3: trading_date 의미 재정의 — 자산 슬롯은 영구적인데 현재는 일일 리셋. 일/다일 경계, 일일 회계와의 관계(issue #20 직결). - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **영구 슬롯.** 슬롯 키 = `portfolio_id`(날짜 없음; 다중 인스턴스 공유 DB 라 실제 유일성 제약은 OQ-7 에서 `UNIQUE(instance_key, portfolio_id)` 복합키로 정련), 슬롯 행은 날 경계로 리셋되지 않고 자산이 universe 에 있는 동안 영속(holding 이 날 경계를 그대로 넘어감 — issue #20). **trading_date 는 슬롯의 정체성에서 제거되고, 이벤트/원장/정책의 시간 속성으로 강등**된다: 일일 활동·회계는 슬롯이 아니라 `slot_transition_log`(ts)·ledger·일일 집계를 날짜로 필터해서 본다. 슬롯 행의 기존 `trading_date NOT NULL` 컬럼은 드롭하거나 의미 변경(`opened_at`/`last_activity_date` 등)한다(스키마 변경). 일일 preallocation(dcy-014 `preallocate_daily_slots`/00:00 트리거)은 **폐기**하고 슬롯 생성/소멸을 universe reconcile(OQ-2)로 대체한다 — 단 trading_date 의 KST 계산 자체(dcy-014/REQ-005)는 일일 회계 경계용으로 **일부 존속(재해석)**, 완전 폐기 아님. - 근거: 슬롯=자산 포지션은 본질적으로 다일 보유이므로 일일 리셋과 충돌. 영구 슬롯은 풀 모델 부산물(일일 preallocation·`no_idle_slot`·closed 재할당 dcy-019·00:00 경계 미생성 issue #16)을 개념적으로 소멸시키고, lifecycle 을 날짜 축에서 떼어 universe 멤버십에만 반응하게 해 OQ-2 와 FR-3(holding 로컬 영속)에 정합한다. - 반영: FR-1, §3 현재/기대 상태, §4, §영향 범위, R-1, §10 DECIDE. dcy-014 폐기/재해석 범위 명시(FR-5). - OQ-4: 포지션 사이징(issue #1, 활성 슬롯 수량 변경)을 본 주기에 포함할지, 토대만 깔고 별도 주기로 분리할지. - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **분리 (Out of Scope). 본 주기는 토대만.** 포지션 사이징(활성 슬롯 보유 수량 변경)과 선언형 target intent(issue #1)는 **별도 후속 Discovery** 로 둔다. - 근거: dcy-020 은 이미 substrate 재설계 + 일일행→영구행 cutover(R-1 High) + 스키마 변경 + dcy-014/019 폐기로 거대하다. 신규 거래 능력(수량 변경)을 얹으면 모델 마이그레이션과 뒤엉켜 회귀 분리·cutover 검증이 불가능해진다. 게다가 우리가 정한 토대(영구 자산 슬롯·holding 로컬·수량 hub 정본+미러·청산 수량 브로커 조회, FR-3/FR-4)가 사이징을 깔끔히 받쳐주므로 미뤄도 손해 없이 후속이 더 쉬워진다. 선언형 target 은 intent 계약 변경(자체 OQ 묶음: 델타 계산·부분체결·오버슈트·rebalancing·M 캡 상호작용)이라 독립 주기가 맞다. issue #20(다일 보유)의 핵심 가치는 영구 슬롯(OQ-3)으로 이미 실현. - **토대 가드(이번 주기 필수, 재작업 방지)**: (1) 수량 고정 가정을 모델/스키마/제약에 박지 않는다(수량=hub 정본+미러라 자연히 가변). (2) 상태 의미 경계 고정 — "활성"=포지션 진입(크기는 기존처럼 allocated_capital/qty 로 1회 결정)·종료 시 전량 청산. **HOLDING→HOLDING 수량 변경·부분 매도는 본 주기에서 구현하지 않는다.** - 반영: §범위 경계 In/Out Scope, §4 상태머신 항목, FR-4, §10 DECIDE. - OQ-5: 코어 로컬 holding(FR-3) 과 portfolio-hub `asset_quantity`/브로커 잔고가 **실제로 어긋날 때** 해소 정책 — 누가 이기고 무슨 행동을 하는가(예: 코어는 holding 인데 브로커 0, 또는 그 반대). 수량 정본 분리(FR-3/FR-4)에서 파생된 잔여 결정. - 상태: Answered (2026-06-10, 사용자 결정) - 권위 모델: ① 즉시 안전 행동 구동 = **코어 로컬 holding**(FR-3, offline); ② 포지션 존재·수량의 reconcile **ground truth = 브로커 잔고**(`get_balance().hldg_qty`, 실계좌); ③ hub `asset_quantity` = 회계(코어 ledger write 의 downstream, 지연 정상 → 대부분 warning, 코어 상태 오류 아님). - 케이스별 해소: - **A. 코어 holding / 브로커 0**(유령 포지션): 조용한 자동 flat 금지 → 슬롯 **`error`(REQ-004 reconcile_mismatch) + WARN + 운영자 resolve**. error 인 동안 safety-sell 대상 제외(유령 청산 시도 중단). - **B. 코어 flat / 브로커 보유**(관리 안 되는 고아 포지션, **최위험**): 큰 **WARN/alert + quarantine/error 격리 + 운영자 결정**(관리 편입 vs 청산 vs 무시). **자동 청산 금지(issue #15)**, **임계값 조작 자동 편입 금지**(cost basis·stop/take 부재 — 편입해도 시간기반 forced/market-close·kill-switch 만 가능). - **C. 둘 다 보유, 수량만 불일치**(holding boolean 일치): 수량은 코어 정본 아님(FR-4) → **브로커 기준 미러 갱신**, hub 지속 불일치는 warning(REQ-031). **상태 변경 없음.** - **D. 코어+브로커 일치, hub 만 다름**(hub 회계 지연): 기존 ledger outbox write-back/재시도(dcy-015/018) + warning. **코어 상태 문제 아님.** - 원칙: (1) **조용한 자동 교정 금지·표면화** — 자동은 비파괴(미러 갱신/warning/error·quarantine 격리)만, 실주문 발생·취소(청산 등)는 **운영자 게이트**(issue #15 자율청산 금지 일관). (2) **감지 = `reconcile_positions`(REQ-031) 확장** — 브로커 잔고 + hub 수량 + **코어 슬롯 holding** 3자 비교. cadence 는 Case B 안전 민감성 때문에 일일 universe refresh 보다 자주 가능(브로커 잔고+슬롯 상태만 필요, 전체 universe fetch 불필요) — 빈도는 tuning. - 경계: **universe-detached 인데 holding = 정상(tombstone, OQ-2)** → OQ-5 아님. OQ-5 는 세 출처의 **비정상 충돌**(A/B/C/D)만. - 기존 자산 재사용(green-field 아님): 감지=REQ-031, 격리/해소=`error`+운영자 resolve(REQ-004), 가시화=warning 오버레이 + safety-sell 카운터/구조화 로그(dcy-017). - 반영: OQ-5 본문(상기), FR-4(브로커 reconcile ground truth), NFR-3, §10 DECIDE. - OQ-6: 동시 활성 최대치 M 의 값·설정 출처는 무엇인가(env / per-instance TOML / 기본값). 기존 `TREX_TOTAL_SLOTS`(풀 크기)는 영구 슬롯 전환으로 폐기되므로 신규 설정 노브가 필요. - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **per-instance TOML 설정(`config/*.toml`)에 둔다** — 예: `max_active_slots`(`DaemonInstanceConfig`, REQ-048 per-instance TOML 계열). 인스턴스별 독립 운영(다중 인스턴스 토폴로지 dcy-009 와 정합), gitignore 되는 인스턴스 파일로 운영자가 인스턴스별 동시 보유 한도를 제어. env(`TREX_*`)·하드코딩 기본값은 비채택(per-instance 일관성·기존 toml 로더 재사용). - 반영: FR-2, §4 capacity 항목, §영향 범위(config), §10 DECIDE. - OQ-7: 다중 인스턴스의 슬롯 영속 스코프 — 인스턴스마다 별도 DB 인가, 공유 DB + 인스턴스 스코프 컬럼인가. 영구 슬롯(FR-1)의 UNIQUE 형태·advisory lock(NFR-1)을 좌우. - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **공유 DB + `instance_key` 스코프.** (1) `daily_slot` 유일성 = **`UNIQUE(instance_key, portfolio_id)`** (+ `instance_key` 컬럼), slot-scoped 테이블 전반(slot_transition_log/intent_log/ledger_outbox/snapshot_pause/killswitch_exclusion 등) instance 스코프화 + 쿼리 필터. (2) advisory lock 을 **인스턴스 스코프화**(`(SLOT_LOCK_ID, hash(instance_key))`)해 인스턴스 간 교차 경합 제거(NFR-1 재정의). (3) `daemon_id` 는 **universe 파티션(get_portfolios) + 감사용**으로만(선택 병행 저장), **스코프 키 아님**; reconcile 시 instance_key↔daemon_id **1:1 정합 가드**(불일치 표면화, 쓰기는 daemon_id 비의존). (4) cutover: 기존 단일 인스턴스 데이터에 instance_key 태깅(R-1). - 근거: 인스턴스별 DB 는 마이그레이션/백업/관측 N배로 비합리적. 메시징이 이미 "브로커 공유 + instance_key 큐 격리"(dcy-009)라 DB 도 동일 패턴이 대칭적. **핵심: 스코프 키를 `instance_key` 로 두어 영속 스토어·락이 portfolio-hub 가용성(whoami→daemon_id)에 의존하지 않음** → 자율 안전 매도 offline 보장(REQ-024)·부팅 즉시 가용·토큰 회전에 안정. daemon_id 의 권위적 소유 이점은 1:1 가드로 흡수. - 반영: FR-1, NFR-1, §영향 범위, R-1, §10 DECIDE. (OQ-3 의 "키=portfolio_id 단독"은 본 OQ-7 로 복합키 `(instance_key, portfolio_id)`로 정련.) - OQ-8: 운영 중 M(`max_active_slots`)을 현재 보유 수보다 작게 변경하면(over-cap) 어떻게 처리하는가. - 상태: Answered (2026-06-10, 사용자 결정) - 결정: **초과분은 신규 활성화만 차단, 기존 보유는 자연 종료까지 유지.** M 을 낮춰 현재 holding 수 > M 이 되어도 코어는 기존 보유를 강제 청산하지 않고(자율청산 금지, issue #15), holding 수가 M 이하로 내려갈 때까지 **새 매수 활성화만 거부**(`capacity_full`)한다. 전략의 명시적 매도로 자연 수렴. - 근거: 강제 청산은 자율청산 원칙·single-writer 안정성과 충돌. FCFS+무치환(OQ-1)과 일관 — capacity 는 "신규 진입 게이트"이지 "보유 강제 축소 트리거"가 아니다. - 반영: FR-2(또는 인접), §10 DECIDE. # 7. 초기 성공 기준 이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다. - S-1: 슬롯 집합이 portfolio-hub universe 자산과 1:1 로 일치한다(universe N개 → 자산 슬롯 N개, portfolio_id 키 일치). - S-2: 동시 활성(holding) 슬롯 수가 항상 ≤ M 이며, 후보 초과 시 OQ-1 규칙대로 결정적으로 활성 자산이 선택된다. - S-3: 매수/매도 신호가 익명 배정 없이 해당 자산 슬롯의 활성화/비활성화로 처리되고, 단일 writer·불변식 회귀가 없다. universe↔slots 표면이 합쳐져 운영 관측이 단일화된다. - S-4: 재정의 상태머신(FR-6: inactive↔pending_buy↔holding↔pending_sell, idle/closed 합침)·intent 자산 키 통일(FR-7: portfolio_id, 중복=`already_active`/무효=`not_holding` 거부)·`trex-core slots` 단일 뷰(FR-8)가 동작하고, over-cap 시 신규만 거부·기존 보유 유지(OQ-8)된다. ## 측정 방식 및 데이터 출처 각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다. - S-1 측정 방식: universe fetch 결과 vs 슬롯 집합 대조(통합 테스트) / 데이터 출처: portfolio-hub `get_portfolios`, daily_slot - S-2 측정 방식: 후보>M 시나리오에서 활성 수·선택 결과 단언 / 데이터 출처: 슬롯 활성 상태 + 선택 규칙 - S-3 측정 방식: 신호→활성화/비활성화 경로 단위·통합 + 동시성 경합 테스트 / 데이터 출처: 슬롯 상태 전이, 전이 로그 - S-4 측정 방식: 상태 전이 단위테스트(허용/거부 집합) + intent 멱등/거부(`already_active`/`not_holding`) 단위 + `slots` 단일 뷰 출력 단언 + over-cap(M 축소) 시나리오 / 데이터 출처: 상태머신 전이표, intent_log, slots RPC 응답 # 8. REQ로 넘기기 전 확인 체크 REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다. - [x] 범위(In Scope/Out of Scope) 확정 - 기준: 포지션 사이징(OQ-4 분리) + 풀 모델 폐기 범위(dcy-001/002/014/019 산출물 명시) 합의 완료(§5 범위 경계). - [x] 성공 지표의 측정 방식/데이터 출처 확정 - 기준: S-1~4 측정 시나리오·데이터 출처가 테스트 가능한 형태로 합의(§7). - [x] High 영향 리스크 우선순위 및 해소 책임자 지정 (비차단으로 이관) - 기준: R-1(풀 모델 폐기·cutover)·R-2(완화됨) 해소 방향은 확정. **해소 책임자(owner) 지정은 사람 책임 배정이라 REQ/batch planning 단계 담당자 할당으로 이관** — Discovery confirm 비차단(confirm-discovery rule 3-4). - [x] 모든 오픈 질문(OQ) `Open` 상태 없음 확인 - 기준: OQ-1~8 전부 Answered, A-1 Confirmed. - [x] Freeze 확정 담당자(CONFIRMED_BY) 지정 - 기준: 승인자 Justin Ko, confirm-discovery 수행(2026-06-10). # 9. 파일 처리 결과 이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다. - 처리 결과: 생성 - 생성 경로: docs/discovery/dcy-020_20260610_asset-centric-slot-model.md - 참조 문서: - docs/discovery/dcy-001_20260603_slot-pure-domain-migration.md (슬롯 도메인·상태머신 — 재해석 대상) - docs/discovery/dcy-014_20260608_trading-date-configurable-timezone-kst.md (일일 preallocation — 폐기/재설계 대상) - docs/discovery/dcy-019_20260609_slot-entry-count-and-closed-reallocation.md (풀 모델 슬롯 재사용 — 폐기 대상) - docs/data-model.md, docs/runtime-flows.md, docs/project-structure.md (baseline — 전면 갱신 대상) - GitHub issue #1(포지션 사이징), #20(중장기 자산 중심) # 10. 사용자 결정 필요 항목 요약 사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다. ## DECIDE - [Decided 2026-06-10] 활성 후보 > M 시 규칙 (OQ-1): **FCFS + 가득 차면 거부, 코어 자율 치환 없음** (tie-break `updated_at`→`portfolio_id`). 능동 배분은 OQ-4 선언형 target 으로 분리. - [Decided 2026-06-10] holding/수량 정본 분리 (FR-3/FR-4): **holding(포지션 열림)=코어 슬롯 로컬 정본(동기 set/clear), 수량(asset_quantity)=portfolio-hub 정본 + 로컬 best-effort 미러, 청산 수량=브로커 잔고 조회.** holding 을 hub `asset_quantity` 로 판단하지 않음(offline 안전·universe 누락 생존·hub 지연·capacity 원자성). 슬롯의 `qty`/`avg_price` 정본 소유(드리프트 원인) 정리. - [Decided 2026-06-10] universe 변동 시 슬롯 lifecycle (OQ-2): **생성=refresh 때 즉시·멱등 / 제거=비활성 soft-retire(행 보존)·보유·pending 은 tombstone 후 닫힐 때 은퇴 / cadence=부팅+일1회(+운영자 on-demand) / degrade·대량소멸 보류 / 단일 writer / 직교 `retired_at` 마커.** - [Decided 2026-06-10] trading_date 시맨틱 (OQ-3): **영구 슬롯(키=`portfolio_id`, `UNIQUE`, 날짜 없음)**, trading_date 는 이벤트/원장/정책의 시간 속성으로 강등, 슬롯 `trading_date` 컬럼 드롭/재의미, 일일 preallocation(dcy-014) 폐기·재해석(KST 회계 경계는 존속). cutover(일일행→영구행+보유 carry-over)는 R-1. - [Decided 2026-06-10] 포지션 사이징 범위 (OQ-4): **분리(Out of Scope) — 본 주기 토대만.** 포지션 사이징·선언형 target intent(issue #1)는 별도 후속 Discovery. 토대 가드: 수량 가변 전제 유지 + "활성=진입/종료=전량 청산" 상태 경계 고정(HOLDING→HOLDING·부분 매도 미구현). - [Decided 2026-06-10] holding↔hub/broker 불일치 해소 (OQ-5): **ground truth=브로커, 코어 holding=즉시 안전 구동, hub 차이=warning.** A(코어 holding/브로커 0)=error+운영자, B(코어 flat/브로커 보유, 최위험)=alert+격리+운영자(자동청산·자동편입 금지), C(수량만)=미러 갱신+warning, D(hub 지연)=기존 write-back. 감지=REQ-031 reconcile 확장, 자동은 비파괴만·실주문은 운영자 게이트. universe-detached holding(정상)=tombstone(OQ-2)과 구분. - [Decided 2026-06-10] 동시 활성 최대치 M 설정 출처 (OQ-6): **per-instance TOML(`config/*.toml`, 예: `max_active_slots`, `DaemonInstanceConfig`/REQ-048 계열).** 인스턴스별 독립 운영, env·하드코딩 기본값 비채택. 기존 `TREX_TOTAL_SLOTS`(풀 크기)는 폐기. - [Decided 2026-06-10] 슬롯 영속 인스턴스 스코프 (OQ-7): **공유 DB + `instance_key` 스코프.** `UNIQUE(instance_key, portfolio_id)` + slot-scoped 테이블 전반 instance 스코프화, advisory lock 인스턴스 스코프화(NFR-1 재정의), `daemon_id` 는 universe 파티션·감사용(스코프 키 아님)·instance_key↔daemon_id 1:1 가드. 인스턴스별 별도 DB 비채택. 핵심: 스코프 키를 instance_key 로 두어 영속·락이 portfolio-hub 가용성 비의존(offline 안전). - [Decided 2026-06-10] over-cap(M 축소) 처리 (OQ-8): **초과분은 신규 활성화만 차단, 기존 보유는 자연 종료까지 유지** — 강제 청산 없음(issue #15), holding ≤ M 될 때까지 새 매수 `capacity_full` 거부. ## CONFIRM - [Confirmed 2026-06-10] 제품 방향이 "universe 자산 중심 포지션 관리 + 동시 보유 수 제어"(익명 capacity 풀 아님)임을 확정 (A-1) — 모델 전환의 대전제. 사용자 확정. ## DATA - 없음 (외부 데이터 의존 없음 — 내부 도메인/모델 결정) # 11. Discovery Freeze REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다. ## 섹션 참조 - 범위: [# 5. 요구사항 목록 > 범위 경계](#5-요구사항-목록) - 리스크/오픈 질문: [# 6. 리스크/가정 목록](#6-리스크가정-목록) - 성공 기준: [# 7. 초기 성공 기준](#7-초기-성공-기준) - 인계 전 확인: [# 8. REQ로 넘기기 전 확인 체크](#8-req로-넘기기-전-확인-체크) - 사용자 결정 필요: [# 10. 사용자 결정 필요 항목 요약](#10-사용자-결정-필요-항목-요약) ## Freeze 플래그 - Handoff Decision: 승인 - Handoff Rationale: OQ-1~8 전부 Answered + 대전제 A-1 Confirmed + FR-1~8/NFR-1~5 확정 + holding/수량 정본 분리(FR-3/FR-4)·인스턴스 스코프(OQ-7)·over-cap(OQ-8) 결정. C-type placeholder 0개, Open OQ 0개, §10 DECIDE/CONFIRM 전부 해소. R-1(풀 모델 폐기·일일행→영구행 cutover)·R-2 해소 **책임자 지정은 REQ/batch planning 단계 담당자 할당으로 이관(비차단, rule 3-4)**. 승인자 Justin Ko 확정 → REQ Drafting 인계 가능. - Ready for REQ Drafting: true - Confirmed By: Justin Ko - Confirmed At (KST): 2026-06-10 10:00 KST