Files
trex-core/docs/discovery/dcy-020_20260610_asset-centric-slot-model.md
T
genichinandClaude Opus 4.8 c369d4d1ee docs(discovery): new-discovery dcy-027 (중장기 전략 슬롯 운영, issue #20)
dcy-020 Out-of-Scope "중장기 전용 운영" 이월 주기. dcy-020 후속 Discovery
참조에 dcy-027 추가, discovery 인덱스에 dcy-027(draft) 행 추가.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:58:50 +09:00

48 KiB
Raw Blame History

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-001004, BAT-001023)와 방금 출시한 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 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.

  • 범위(In Scope/Out of Scope) 확정
    • 기준: 포지션 사이징(OQ-4 분리) + 풀 모델 폐기 범위(dcy-001/002/014/019 산출물 명시) 합의 완료(§5 범위 경계).
  • 성공 지표의 측정 방식/데이터 출처 확정
    • 기준: S-1~4 측정 시나리오·데이터 출처가 테스트 가능한 형태로 합의(§7).
  • High 영향 리스크 우선순위 및 해소 책임자 지정 (비차단으로 이관)
    • 기준: R-1(풀 모델 폐기·cutover)·R-2(완화됨) 해소 방향은 확정. 해소 책임자(owner) 지정은 사람 책임 배정이라 REQ/batch planning 단계 담당자 할당으로 이관 — Discovery confirm 비차단(confirm-discovery rule 3-4).
  • 모든 오픈 질문(OQ) Open 상태 없음 확인
    • 기준: OQ-1~8 전부 Answered, A-1 Confirmed.
  • 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 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: 승인
  • Handoff Rationale: OQ-18 전부 Answered + 대전제 A-1 Confirmed + FR-18/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