diff --git a/.stage-pilot/bootstrap/baseline.yaml b/.stage-pilot/bootstrap/baseline.yaml new file mode 100644 index 0000000..656a35f --- /dev/null +++ b/.stage-pilot/bootstrap/baseline.yaml @@ -0,0 +1,142 @@ +schema_version: 1 +capture_mode: mixed # declared | observed | mixed + +project: + repository_name: trex-core + display_name: Trex Core + summary: trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다. + primary_domain: 자동매매 일일 거래 슬롯 생명주기 도메인 (equity trading slot lifecycle) + +stack: + tech_stack: + - Python >=3.12 + - pyproject.toml 기반 패키지 (setuptools) + - pytest (단위 테스트) + - ruff (린트) + - storage-agnostic 순수 도메인 (현재 in-memory repository, PostgreSQL/psycopg 는 향후 영속화 단계에서 도입 예정) + +runtime: + primary_runtime: library + primary_entrypoints: + - name: SlotService + purpose: 슬롯 생명주기 도메인 서비스 — preallocate / transit / capacity / entry-count 의 in-process API + - name: SlotRepository (Protocol) + purpose: 저장소 추상화 경계 — 구현체(in-memory, 향후 PostgreSQL)를 주입받는 영속화 계약 + +interfaces: + contracts: + - name: SlotService + type: internal-service + actors: 상위 애플리케이션(예: trex-orbit 류 매매 데몬)의 매수/매도/주문 결정 경로 및 운영자 도구 + purpose: 슬롯 상태 전이를 레이스-프리하게 수행하고 일일 슬롯 가용성/재진입 카운트를 계산한다. + stability: internal + inputs: + - preallocate_daily_slots(trading_date, count) :: 거래일 idle 슬롯 멱등 사전 할당 + - transit_slot(slot_id, from_state, to_state, reason, actor, **fields) :: advisory lock 하 원자 상태 전이 + - get_today_entry_count(trading_date, symbol) :: 재진입 정책 입력 조회 + - compute_slot_capacity(trading_date, total_slots) :: idle/holding/pending + scarcity_ratio 스냅샷 + outputs: + - Slot :: 전이 후 슬롯 행 스냅샷 + - SlotCapacity :: 가용성 스냅샷 + - slot_transition_log append :: 모든 전이의 append-only 감사 기록 + errors: + - SlotTransitionError :: 허용되지 않은 (from_state, to_state) 전이 + - SlotStateMismatchError :: read-write 사이 상태 변동(레이스 감지) + - SlotNotFoundError :: 존재하지 않는 slot_id + compatibility_rules: + - 6 상태 / 8 전이 패밀리 계약을 깨는 변경은 breaking 으로 취급한다. + - 상태 변경 API 는 transactional_advisory_lock 안에서만 수행하고 lock 보유 중 외부 I/O 를 금지한다. + - name: SlotRepository (Protocol) + type: internal-service + actors: SlotService(소비) ↔ 저장소 구현체(InMemorySlotRepository / 향후 PostgreSQLSlotRepository) + purpose: 도메인을 특정 저장소 기술에서 분리하는 영속화 경계 계약. + stability: internal + inputs: + - transactional_advisory_lock(lock_id) :: 단일 트랜잭션 + advisory lock 컨텍스트 + - fetch_slot / update_slot / pre_allocate_slots / find_idle_slot :: daily_slot CRUD + - append_transition_log :: append-only 전이 로그 + - increment_symbol_entry / get_symbol_entry_count :: 재진입 카운터 + - count_slots_by_status :: 상태별 집계 + outputs: + - Slot / SlotTransitionRecord / 카운트 dict :: 도메인 모델 형태로 반환 + errors: + - SlotNotFoundError :: update 대상 row 부재 + compatibility_rules: + - 구현체는 advisory lock 직렬화와 append-only 전이 로그 의미를 반드시 보장한다. + shared_constraints: + - 도메인은 외부 의존(브로커, DB 드라이버 등)을 직접 호출하지 않는다(순수 도메인 경계). + - 모든 상태 변경은 단일 advisory lock(SLOT_ADVISORY_LOCK_ID)으로 직렬화한다. + current_gaps: + - 영속화 구현체(PostgreSQL)와 그에 딸린 SQL 스키마/마이그레이션은 이번 이관 범위 밖이며 향후 도입 예정. + - CLI / 설정(config) 표면은 아직 없음(trex-orbit 의 trex slot CLI 는 이식하지 않음). + - 패키지 네임스페이스(app.domain.slot vs trex_core.domain.slot)는 첫 Discovery 에서 확정(plan.md OQ-1). + +structure: + planned_top_level_areas: + - path: app/domain/slot/ + responsibility: 슬롯 생명주기 순수 도메인(state/models/errors/repository protocol/service/in-memory repo) + - path: tests/domain/slot/ + responsibility: 슬롯 도메인 단위 테스트(상태머신/서비스) + - path: docs/ + responsibility: SDLC baseline 문서 및 active index(discovery/srs/batches/releases) + - path: pyproject.toml + responsibility: 패키지 메타 + pytest/ruff 설정 + +data_model: + persistence_backend: storage-agnostic (SlotRepository Protocol 경유) — 현재 in-memory, 향후 PostgreSQL 예정 + entities: + - name: Slot + purpose: 하나의 일일 거래 슬롯의 현재 생명주기 상태와 점유 정보를 담는 source of truth. + source_of_truth: daily_slot (향후 테이블) / 현재는 in-memory dict + lifecycle: idle -> pending_buy -> holding -> pending_sell -> closed -> (recovery) idle ; 모든 상태 -> error + key_fields: + - slot_id :: UUID :: 슬롯 식별자(PK) + - trading_date :: date :: 거래일 + - status :: SlotState :: 6 상태 중 현재 상태 + - symbol :: str? :: 점유 종목 + - qty / avg_price / entry_price / allocated_capital :: numeric? :: 포지션/배정 정보 + - strategy_id / sell_strategy_id :: str? :: 진입/청산 전략 식별 + - broker_order_id / portfolio_id / order_id :: str? :: 주문/포트폴리오 핸들 + - forced_close_at :: datetime? :: 강제 청산 마감선 + - created_at / updated_at :: datetime? :: 타임스탬프 + relationships: + - daily_symbol_entries :: closed->idle 복구 시 (trading_date, symbol) 카운트 +1 + - slot_transition_log :: 매 전이마다 append-only 기록 1행 + state_rules: + - 8 전이 패밀리에 없는 전이는 거부한다. + - 전이 전 current state == from_state 여야 한다(레이스 감지). + - closed->idle / pending_buy->idle 복구 시 점유 필드를 초기화한다. + - name: SlotTransitionRecord + purpose: 슬롯 상태 전이의 append-only 감사 기록. + source_of_truth: slot_transition_log (향후 테이블) / 현재는 in-memory list + lifecycle: append-only (UPDATE/DELETE 금지) + key_fields: + - slot_id :: UUID :: 대상 슬롯 + - from_state / to_state :: SlotState :: 전이 전후 상태 + - ts :: datetime :: 전이 시각(UTC) + - reason / actor :: str :: 전이 사유와 주체 + - extra :: dict :: 부가 컨텍스트(예: symbol) + relationships: + - Slot :: slot_id 로 연결 + state_rules: + - 오직 INSERT 만 허용한다. + consistency_rules: + - (trading_date, symbol) 재진입 카운트는 closed->idle 복구와 원자적으로 증가한다. + - 모든 상태 변경과 전이 로그 append 는 동일 advisory-locked 트랜잭션 안에서 일어난다. + persistence_notes: + - 현재는 InMemorySlotRepository(threading.Lock 으로 advisory lock 모사)만 제공한다. + - 향후 PostgreSQL 구현 시 부록의 컬럼 계약(plan.md 부록 A)을 만족해야 한다. + current_gaps: + - daily_slot / daily_symbol_entries / slot_transition_log 의 물리 스키마(DDL)는 미이식 — 영속화 단계에서 작성. + +notes: + known_unknowns: + - 패키지 네임스페이스 결정(app.domain.slot vs trex_core.domain.slot) — plan.md OQ-1 + - SLOT_ADVISORY_LOCK_ID 의 소속(순수 도메인 잔류 vs 영속화 계층 이동) — plan.md OQ-2 + - 영속화 backend 선택 및 SQL 스키마 재구성 시점 + - trex-orbit 과의 향후 코드 수렴 여부(현재는 병행) + +metadata: + captured_at_kst: 2026-06-03 00:00 + source: bootstrap-baseline-questionnaire + updated_from: mixed diff --git a/docs/batches/index.md b/docs/batches/index.md new file mode 100644 index 0000000..158750c --- /dev/null +++ b/docs/batches/index.md @@ -0,0 +1,10 @@ +# Batch Index + +## 목적 +- 이 문서는 batch delivery 단위의 전역 인덱스다. +- 각 batch는 `docs/batches//` 아래에서 profile(`standard` | `batch-lite`)에 맞는 산출물을 관리한다. + +## Batch Register + +| BAT ID | Profile | Status | Included REQ | Discovery | Folder | +| --- | --- | --- | --- | --- | --- | diff --git a/docs/data-model.md b/docs/data-model.md new file mode 100644 index 0000000..5bb9936 --- /dev/null +++ b/docs/data-model.md @@ -0,0 +1,115 @@ +# Trex Core Data Model + +- Baseline Mode: mixed +- Baseline Seed: .stage-pilot/bootstrap/baseline.yaml +- Status: draft +- Owner: project maintainers +- Last Updated (KST): 2026-06-03 +- Source Discovery / Batch: bootstrap-baseline (pre-Discovery) + +## Project Summary +- trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다. + +## Primary Domain +- 자동매매 일일 거래 슬롯 생명주기 도메인 (equity trading slot lifecycle) + +## Primary Persistence Backend +- storage-agnostic (SlotRepository Protocol 경유) — 현재 in-memory, 향후 PostgreSQL 예정 + +## Purpose +- This document captures the approved cross-cutting data model baseline for the project. +- It is a shared reference for REQ drafting, batch design, implementation, verification, migration planning, and handoff. + +## Scope +- Covers core entities, relationships, states, persistence mappings, and shared consistency rules. +- Does not duplicate full functional acceptance criteria already owned by REQ documents. +- Does not replace ORM definitions, migration files, or generated schema artifacts. + +## Model Summary + +- Slot :: 하나의 일일 거래 슬롯의 현재 생명주기 상태/점유 정보(source of truth) +- SlotTransitionRecord :: 슬롯 상태 전이의 append-only 감사 기록 +- daily_symbol_entries (카운터) :: (trading_date, symbol) 별 재진입 횟수(결정 입력) +- SlotCapacity (계산 스냅샷) :: idle/holding/pending + scarcity_ratio (영속 엔티티 아님) + +## Entity: `Slot` + +- Purpose: 하나의 일일 거래 슬롯의 현재 생명주기 상태와 점유 정보를 담는 source of truth. +- Source of Truth: daily_slot (향후 테이블) / 현재는 in-memory dict +- Lifecycle: idle -> pending_buy -> holding -> pending_sell -> closed -> (recovery) idle ; 모든 비-error 상태 -> error ; error -> {idle, holding} + +### Key Fields + +- slot_id :: UUID :: 슬롯 식별자(PK) +- trading_date :: date :: 거래일 +- status :: SlotState :: 6 상태(idle/pending_buy/holding/pending_sell/closed/error) 중 현재 상태 +- symbol :: str? :: 점유 종목 +- qty / avg_price / entry_price :: numeric? :: 수량 / 평단 / 진입가 +- allocated_capital :: numeric? :: 배정 자본 +- order_id / broker_order_id :: str? :: 주문 식별자(자유 주석 / 브로커 핸들) +- strategy_id / sell_strategy_id :: str? :: 진입/청산 전략 식별 +- portfolio_id :: str? :: 포트폴리오 식별 +- forced_close_at :: datetime? :: 강제 청산 마감선 +- created_at / updated_at :: datetime? :: 생성/갱신 시각 + +### Relationships + +- daily_symbol_entries :: closed->idle 복구 시 (trading_date, symbol) 카운트 +1 +- slot_transition_log :: 매 전이마다 append-only 기록 1행 + +### State Rules + +- 8 전이 패밀리에 없는 전이는 거부한다. +- 전이 전 current status == from_state 여야 한다(레이스 감지). +- closed->idle / pending_buy->idle 복구 시 점유 필드(symbol/qty/.../forced_close_at)를 초기화한다. + +## Entity: `SlotTransitionRecord` + +- Purpose: 슬롯 상태 전이의 append-only 감사 기록. +- Source of Truth: slot_transition_log (향후 테이블) / 현재는 in-memory list +- Lifecycle: append-only (UPDATE/DELETE 금지) + +### Key Fields + +- slot_id :: UUID :: 대상 슬롯 +- from_state / to_state :: SlotState :: 전이 전후 상태 +- ts :: datetime :: 전이 시각(UTC) +- reason :: str :: 전이 사유 +- actor :: str :: 전이 주체(시스템 워커 / 운영자) +- extra :: dict :: 부가 컨텍스트(예: symbol) + +### Relationships + +- Slot :: slot_id 로 연결 + +### State Rules + +- 오직 INSERT 만 허용한다(append-only). + +## Shared Consistency Rules + +- (trading_date, symbol) 재진입 카운트는 closed->idle 복구와 원자적으로 증가한다. +- 모든 상태 변경과 전이 로그 append 는 동일 advisory-locked 트랜잭션 안에서 일어난다. +- 재진입 정책 결정 입력은 daily_symbol_entries 카운터에서 읽고, slot_transition_log(감사 전용)를 join 하지 않는다. + +## Persistence / Integration Notes + +- 현재는 InMemorySlotRepository(threading.Lock 으로 advisory lock 모사)만 제공한다. +- 향후 PostgreSQL 구현 시 plan.md 부록 A 의 컬럼 계약(타입 포함)을 만족해야 한다. +- daily_symbol_entries PK = (trading_date, symbol); slot_transition_log 는 append-only 시퀀스. + +## Current Gaps / Planned Changes + +- daily_slot / daily_symbol_entries / slot_transition_log 의 물리 스키마(DDL)는 미이식 — 영속화 단계에서 작성. +- daily_slot_archive(EOD 아카이브)와 retention prune 은 trex-orbit 인프라 기능으로, 이번 순수 도메인 범위 밖. +- SlotState/필드 계약을 코드와 문서 사이에서 드리프트 없이 유지할 방법은 첫 Discovery 에서 정의(plan.md OQ-4). + +## Update Triggers + +- Update this document when a core entity, key field, or relationship changes. +- Update this document when lifecycle or persistence behavior changes. +- Update this document when a batch introduces a migration, backfill, or breaking data assumption. + +## Change Log + +- 2026-06-03 :: bootstrap-baseline 으로 초기 데이터 모델 baseline 생성(Slot + SlotTransitionRecord + 재진입 카운터). diff --git a/docs/discovery/index.md b/docs/discovery/index.md new file mode 100644 index 0000000..8c9f028 --- /dev/null +++ b/docs/discovery/index.md @@ -0,0 +1,8 @@ +# Discovery 전체 인덱스 + + + +## Discovery 목록 + +| ID | 날짜 | 이슈명 | 문서 | 상태 | +|---|---|---|---|---| \ No newline at end of file diff --git a/docs/interface-contract.md b/docs/interface-contract.md new file mode 100644 index 0000000..c6cf41e --- /dev/null +++ b/docs/interface-contract.md @@ -0,0 +1,113 @@ +# Trex Core Interface Contract + +- Baseline Mode: mixed +- Baseline Seed: .stage-pilot/bootstrap/baseline.yaml +- Status: draft +- Owner: project maintainers +- Last Updated (KST): 2026-06-03 +- Source Discovery / Batch: bootstrap-baseline (pre-Discovery) +- Primary Runtime: library + +## Project Summary +- trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다. + +## Primary Domain +- 자동매매 일일 거래 슬롯 생명주기 도메인 (equity trading slot lifecycle) + +## Purpose +- This document captures the approved external and cross-boundary interface contracts for the project. +- It is a cross-cutting reference for REQ drafting, batch design, implementation, verification, and handoff. + +## Scope +- Covers in-process domain-service APIs and the persistence boundary Protocol (library 형태라 외부 HTTP/CLI 표면은 아직 없음). +- Does not duplicate full business requirements already owned by REQ documents. +- Does not replace low-level code references or generated API artifacts. + +## Interface Summary + +- SlotService :: 슬롯 생명주기 도메인 서비스(전이/사전할당/가용성/재진입 카운트) +- SlotRepository (Protocol) :: 도메인 ↔ 저장소 경계 계약 + +## Interface: `SlotService` + +- Type: internal-service +- Consumers / Producers: 상위 애플리케이션(예: trex-orbit 류 매매 데몬)의 매수/매도/주문 결정 경로 및 운영자 도구 +- Purpose: 슬롯 상태 전이를 레이스-프리하게 수행하고 일일 슬롯 가용성/재진입 카운트를 계산한다. +- Stability: internal + +### Inputs + +- preallocate_daily_slots(trading_date, count) :: 거래일 idle 슬롯 멱등 사전 할당 (count > 0) +- transit_slot(slot_id, from_state, to_state, reason, actor, **fields) :: advisory lock 하 원자 상태 전이 +- get_today_entry_count(trading_date, symbol) :: 재진입 정책 입력 조회 +- compute_slot_capacity(trading_date, total_slots) :: 가용성 스냅샷 계산 (total_slots > 0) + +### Outputs + +- Slot :: 전이 후 슬롯 행 스냅샷 +- SlotCapacity :: idle/holding/pending 카운트 + scarcity_ratio +- int :: 사전 할당 수 / 재진입 카운트 +- slot_transition_log append :: 모든 전이의 append-only 감사 기록(부수 효과) + +### Error Contract + +- SlotTransitionError :: 허용되지 않은 (from_state, to_state) 전이 +- SlotStateMismatchError :: read-write 사이 상태 변동(레이스 감지) +- SlotNotFoundError :: 존재하지 않는 slot_id +- ValueError :: count <= 0 또는 total_slots <= 0 + +### Compatibility Rules + +- 6 상태 / 8 전이 패밀리 계약을 깨는 변경은 breaking 으로 취급한다. +- 상태 변경 API 는 transactional_advisory_lock 안에서만 수행하고 lock 보유 중 외부 I/O 를 금지한다. + +## Interface: `SlotRepository (Protocol)` + +- Type: internal-service +- Consumers / Producers: SlotService(소비) ↔ 저장소 구현체(InMemorySlotRepository / 향후 PostgreSQLSlotRepository) +- Purpose: 도메인을 특정 저장소 기술에서 분리하는 영속화 경계 계약. +- Stability: internal + +### Inputs + +- transactional_advisory_lock(lock_id) :: 단일 트랜잭션 + advisory lock 컨텍스트 매니저 +- pre_allocate_slots / fetch_slot / find_idle_slot / update_slot :: daily_slot CRUD +- append_transition_log :: append-only 전이 로그 +- increment_symbol_entry / get_symbol_entry_count :: 재진입 카운터 +- count_slots_by_status :: 상태별 집계 + +### Outputs + +- Slot / SlotTransitionRecord :: 도메인 모델 +- dict[SlotState, int] :: 상태별 카운트 +- int :: 재진입 카운트 / 사전 할당 수 + +### Error Contract + +- SlotNotFoundError :: update 대상 row 부재 + +### Compatibility Rules + +- 구현체는 advisory lock 직렬화와 append-only 전이 로그 의미를 반드시 보장한다. +- 구현체는 lock 보유 중 외부 I/O 를 수행하지 않는다. + +## Shared Constraints + +- 도메인은 외부 의존(브로커, DB 드라이버 등)을 직접 호출하지 않는다(순수 도메인 경계). +- 모든 상태 변경은 단일 advisory lock(SLOT_ADVISORY_LOCK_ID)으로 직렬화한다. + +## Current Gaps / Planned Changes + +- 영속화 구현체(PostgreSQL)와 그에 딸린 SQL 스키마/마이그레이션은 이번 이관 범위 밖이며 향후 도입 예정. +- 외부 HTTP API / CLI 표면 없음(trex-orbit 의 `trex slot` CLI 미이식). +- 패키지 네임스페이스 결정(plan.md OQ-1)에 따라 import 경로 계약이 확정된다. + +## Update Triggers + +- Update this document when an externally visible API, event, CLI, or file contract changes. +- Update this document when a batch changes compatibility, validation, or error behavior. +- Update this document when a new external consumer or producer is introduced. + +## Change Log + +- 2026-06-03 :: bootstrap-baseline 으로 초기 인터페이스 계약 baseline 생성(SlotService + SlotRepository Protocol). diff --git a/docs/project-structure.md b/docs/project-structure.md new file mode 100644 index 0000000..008ea76 --- /dev/null +++ b/docs/project-structure.md @@ -0,0 +1,107 @@ +# Trex Core Project Structure + +- Baseline Mode: mixed +- Baseline Seed: .stage-pilot/bootstrap/baseline.yaml +- Status: draft +- Owner: project maintainers +- Last Updated (KST): 2026-06-03 +- Source Discovery / Batch: bootstrap-baseline (pre-Discovery, 3-phase lifecycle 밖의 bootstrap 산출물) + +## Project Summary +- trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다. + +## Primary Domain +- 자동매매 일일 거래 슬롯 생명주기 도메인 (equity trading slot lifecycle) + +## Tech Stack +- Python >=3.12 +- pyproject.toml 기반 패키지 (setuptools) +- pytest (단위 테스트) +- ruff (린트) +- storage-agnostic 순수 도메인 (현재 in-memory repository, PostgreSQL/psycopg 는 향후 영속화 단계에서 도입 예정) + +## Primary Runtime +- Type: library +- Planned Entry Points: + - SlotService :: 슬롯 생명주기 도메인 서비스 — preallocate / transit / capacity / entry-count 의 in-process API + - SlotRepository (Protocol) :: 저장소 추상화 경계 — 구현체(in-memory, 향후 PostgreSQL)를 주입받는 영속화 계약 + +## Purpose +- This document is the current approved repository and package structure baseline. +- It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates. + +## Scope +- Covers the top-level repository layout and package/module boundaries. +- Does not duplicate detailed business rules, acceptance criteria, or implementation-only function signatures. + +## Top-Level Structure + +```text +. +├── .github/ # Copilot instructions + StagePilot skill entrypoints +│ ├── instructions/ +│ └── skills/ +├── .stage-pilot/ # StagePilot 도구/템플릿/부트스트랩 seed +│ ├── bootstrap/ +│ │ └── baseline.yaml +│ └── templates/ +├── docs/ # SDLC baseline 문서 + active index +│ ├── batches/index.md +│ ├── discovery/index.md +│ ├── releases/index.md +│ ├── srs/index.md +│ ├── data-model.md +│ ├── interface-contract.md +│ ├── project-structure.md +│ └── runtime-flows.md +├── CLAUDE.md # SDLC governance instructions +└── (planned) + ├── pyproject.toml # 패키지 메타 + pytest/ruff 설정 + ├── app/ + │ └── domain/ + │ └── slot/ # 이식 대상 순수 도메인 + └── tests/ + └── domain/slot/ # 도메인 단위 테스트 +``` + +> 참고: 위 `(planned)` 항목은 slot 순수 도메인 이관 Batch 에서 생성될 예정 구조다(plan.md). 현재 저장소에는 아직 코드가 없고 governance/문서 스캐폴딩만 존재한다. + +## Package / Module Responsibilities + +- `app/domain/slot/` (planned) + - 슬롯 생명주기 순수 도메인. 6 상태 머신(`state.py`), 데이터 모델(`models.py`), 예외(`errors.py`), 저장소 계약(`repository.py` Protocol), 도메인 서비스(`service.py`), 테스트용 in-memory 구현(`in_memory_repository.py`). + - 외부 의존 0 — stdlib 와 패키지 내부 참조만 사용. +- `tests/domain/slot/` (planned) + - 상태머신/서비스 단위 테스트. InMemorySlotRepository 기반으로 실제 DB 없이 검증. +- `docs/` + - SDLC baseline(구조/흐름/인터페이스/데이터 모델) 및 active index(discovery/srs/batches/releases). +- `pyproject.toml` (planned) + - 패키지 메타데이터, 의존성, pytest/ruff 설정. + +## Dependency Rules + +- 순수 도메인(`app/domain/slot/`)은 저장소 구현, 브로커, 네트워크, CLI 등 인프라에 직접 의존하지 않는다. +- 저장소 접근은 오직 `SlotRepository` Protocol 을 통해서만 이뤄지고 구현체는 주입된다. +- 인프라(향후 PostgreSQL 구현, CLI, config)는 도메인을 의존할 수 있으나 그 역은 금지한다. + +## Shared Boundaries + +- `SlotRepository` Protocol 이 도메인 ↔ 저장소 사이의 단일 경계다. +- `SLOT_ADVISORY_LOCK_ID` 상수가 모든 상태 변경 직렬화의 공유 기준점이다. + +## Current Gaps / Planned Changes + +- 영속화 구현체(PostgreSQL repository)와 SQL 스키마/마이그레이션은 이번 범위 밖 — 향후 도입. +- CLI / 설정(config) 표면 없음(trex-orbit 의 `trex slot` CLI 미이식). +- 패키지 네임스페이스(`app.domain.slot` vs `trex_core.domain.slot`)는 첫 Discovery 에서 확정(plan.md OQ-1). +- `pyproject.toml` 및 `app/`, `tests/` 스캐폴딩은 이관 Batch 에서 생성 예정. + +## Update Triggers + +- Update this document when package boundaries change. +- Update this document when new top-level runtime or domain modules are added. +- Update this document when a batch changes the approved structure baseline. + +## Change Log + +- 2026-06-03 :: bootstrap-baseline 으로 초기 구조 baseline 생성(mixed: trex-orbit 코드 관찰 + 이관 계획 선언). diff --git a/docs/releases/index.md b/docs/releases/index.md new file mode 100644 index 0000000..1b66789 --- /dev/null +++ b/docs/releases/index.md @@ -0,0 +1,10 @@ +# Release Index + +## 목적 +- 이 문서는 release 단위의 전역 인덱스다. +- 각 release는 하나 이상의 release-candidate batch를 묶고, profile(`docs-only` | `tooling` | `app-service`)에 맞는 배포와 후속 환류를 추적한다. + +## Release Register + +| REL ID | Profile | Status | Included Batch | Discovery/REQ Input | Link | +| --- | --- | --- | --- | --- | --- | diff --git a/docs/runtime-flows.md b/docs/runtime-flows.md new file mode 100644 index 0000000..2fd7f46 --- /dev/null +++ b/docs/runtime-flows.md @@ -0,0 +1,72 @@ +# Trex Core Runtime Flows + +- Baseline Mode: mixed +- Baseline Seed: .stage-pilot/bootstrap/baseline.yaml +- Status: draft +- Owner: project maintainers +- Last Updated (KST): 2026-06-03 +- Source Discovery / Batch: bootstrap-baseline (pre-Discovery) +- Primary Runtime: library + +## Project Summary +- trex 제품군의 공용 베이스로, 첫 도메인으로 trex-orbit 의 일일 거래 슬롯 생명주기(slot) 순수 도메인을 storage-agnostic 하게 이식한 코어다. + +## Purpose +- This document is the current approved execution-flow baseline for the project. +- It is a cross-cutting reference document for Discovery, REQ, Batch Design, Batch Verification, and implementation updates. + +## Scope +- Covers representative domain-service flows (library 형태이므로 외부 명령이 아니라 in-process API 호출 흐름). +- Does not duplicate full acceptance criteria or low-level implementation details. + +## Covered Entry Points + +- SlotService :: 슬롯 생명주기 도메인 서비스 (preallocate / transit / capacity / entry-count) +- SlotRepository (Protocol) :: 저장소 구현체 주입 경계 + +## Shared Components + +- SlotRepository Protocol :: 저장소 추상화. 구현체(InMemorySlotRepository, 향후 PostgreSQLSlotRepository)를 주입. +- SLOT_ADVISORY_LOCK_ID :: 모든 상태 변경을 직렬화하는 공유 advisory lock 식별자. +- transactional_advisory_lock :: 단일 트랜잭션 + advisory lock 컨텍스트(외부 I/O 금지). + +## Flow: `slot 사전 할당 (preallocate_daily_slots)` + +1. 호출자가 `preallocate_daily_slots(trading_date, count)` 를 호출한다(count > 0 검증). +2. SlotService 가 `transactional_advisory_lock(SLOT_ADVISORY_LOCK_ID)` 를 획득한다. +3. 저장소가 해당 trading_date 에 슬롯이 이미 있으면 0 을 반환(멱등), 없으면 `count` 개 idle 슬롯을 삽입한다. +4. 삽입된 슬롯 수를 반환한다. + +## Flow: `slot 상태 전이 (transit_slot)` + +1. 호출자가 `transit_slot(slot_id, from_state, to_state, reason, actor, **fields)` 를 호출한다. +2. (from_state, to_state) 가 8 전이 패밀리에 속하는지 먼저 검증한다(아니면 SlotTransitionError). +3. advisory lock 획득 후 슬롯을 fetch 한다(없으면 SlotNotFoundError). +4. 현재 status == from_state 인지 확인한다(아니면 SlotStateMismatchError — 레이스 감지). +5. to_state 의미에 맞춰 점유 필드를 계산하고 슬롯 행을 update 한다. (closed/pending_buy -> idle 은 점유 초기화) +6. closed -> idle 복구면 (trading_date, symbol) 재진입 카운트를 +1 한다. +7. slot_transition_log 에 전이 기록 1행을 append 하고 갱신된 슬롯을 반환한다. +8. 외부 I/O(브로커 등)는 lock 밖에서 호출자가 수행한다(lock 보유 중 금지). + +## Flow Constraints + +- 모든 상태 변경 API 는 advisory-locked 단일 트랜잭션 안에서 수행한다. +- lock 보유 중에는 외부 I/O 를 수행하지 않는다. +- slot_transition_log 는 append-only 다(UPDATE/DELETE 금지). +- 상태 전이는 read(현재 상태)-검증-write 가 동일 트랜잭션에서 원자적으로 이뤄져 레이스를 차단한다. + +## Current Gaps / Planned Changes + +- 실제 영속화(PostgreSQL) 흐름은 미구현 — 현재는 in-memory repository 로만 구동. +- CLI/데몬 런타임 흐름 없음(library). 상위 애플리케이션 통합 흐름은 영속화 단계 이후 정의. +- 강제 청산/EOD 같은 상위 운영 흐름은 이번 순수 도메인 범위 밖. + +## Update Triggers + +- Update this document when a command entry point changes. +- Update this document when a runtime orchestration path changes. +- Update this document when a batch changes the approved flow baseline. + +## Change Log + +- 2026-06-03 :: bootstrap-baseline 으로 초기 흐름 baseline 생성(slot 도메인 in-process API 흐름 기준). diff --git a/docs/srs/index.md b/docs/srs/index.md new file mode 100644 index 0000000..67c789c --- /dev/null +++ b/docs/srs/index.md @@ -0,0 +1,87 @@ +# Software Requirement Specification Index + +## 목적 +- 이 문서는 프로젝트의 SRS 운영 기준과 requirement 목록을 관리하는 entry point이다. +- 개별 requirement의 상세 내용은 타입별 폴더 하위 `req-XXX_*.md` 파일에서 관리한다. + +## 사용 방법 +1. 새로운 requirement가 필요하면 `Next Requirement ID`를 확인하고 `docs/srs/req-template.md`를 복사해 `docs/srs//req-XXX_.md` 파일을 생성한다. +2. 초안 작성은 `draft-req`, 승인 전환은 `confirm-req`, 변경 대응은 `change-req`, 구현 완료 전환은 `confirm-req-implemented` skill을 기준으로 수행한다. +3. 작성 또는 수정 후 누락과 모호성을 점검한다. +4. requirement 추가 또는 변경 후 `Next Requirement ID`, `Requirement Register`, `Recent Change Log Summary`를 함께 갱신한다. +5. `Proposed` requirement를 승인하려면 승인 준비 상태와 blocker를 점검한다. +6. `Approved` requirement는 구현 이슈나 작업 항목으로 연결한다. +7. 구현과 검증이 끝난 requirement는 `confirm-req-implemented` skill로 완료 전환 가능 여부를 점검한다. +8. requirement 변경 시 `change-req` skill을 기준으로 해당 REQ 파일의 `Change Log`를 먼저 갱신한 뒤 본문을 수정한다. +9. 구현 전에는 관련 REQ 파일과 최근 `Change Log`를 기준으로 변경 범위를 판단한다. + +## 상태 정의 +- Proposed: 초안 상태이며 구현 기준으로 확정되지 않음 +- Approved: 구현 기준으로 승인됨 +- Implemented: 구현과 검증이 완료됨 +- Deprecated: 더 이상 유지하지 않음 + +## Status Transition Evidence + +### Proposed -> Approved +- `Status`, `Type`, `Priority`, `Owner`, `Intent`, `Requirement`, `Acceptance Criteria`, `Impacted Area`, `Change Log`가 모두 존재해야 한다. +- `Type`은 아래 분류 도표에서 정확하게 하나로 지정되어야 한다. +- `Acceptance Criteria`는 구현 판단에 사용할 수 있을 정도로 구체적이어야 한다. +- 미해결 assumption 또는 open question이 있으면 `Notes`에 명시하고, 승인 blocker 여부를 판단해야 한다. +- 승인 전환 시 해당 REQ 파일의 `Change Log`에 status 변경 사유를 기록해야 한다. + +### Approved -> Implemented +- 각 `Acceptance Criteria`에 대해 test, manual verification, 또는 구현 결과 중 최소 1개의 evidence가 있어야 한다. +- evidence는 requirement 문서 자체 또는 연결된 구현/검증 결과에서 추적 가능해야 한다. +- 미충족 `Acceptance Criteria`가 있으면 `Implemented`로 전환하지 않는다. +- 구현 완료 전환 시 잔여 리스크와 미검증 영역이 있으면 `Change Log`에 기록해야 한다. +- 상태 전환은 `confirm-req-implemented` skill을 기준으로 수행한다. + +### Requirement Change Handling +- 기존 REQ 본문(`Requirement`, `Acceptance Criteria`, `Impacted Area`)을 수정하기 전에는 새 `Change Log` 항목을 만든다. +- `Change Log`에는 최소한 `Acceptance Criteria Delta`, `Impacted Area Delta`, `Delivery Trace Delta`, `Revalidation Impact`, `Validation Plan`이 포함되어야 한다. +- 변경이 기존 구현 또는 verification evidence를 무효화하면 `Implemented` requirement는 `Approved`로 되돌린다. +- 변경이 승인 전제 자체를 다시 검토하게 만들면 `Approved` 또는 `Implemented` requirement를 `Proposed`로 되돌릴 수 있다. +- 상태 되돌림이 발생하면 `Requirement Register`와 `Recent Change Log Summary`도 함께 갱신한다. + +## Requirement 타입 분류 도표 + +| 타입 | 정의 | 예시 | +|------|------|------| +| **Configuration** | 설정 옵션, 커스터마이징 포인트 | 설정 파라미터, 환경 변수, 옵션 항목 | +| **Data** | 데이터 구조, 저장/로드, 파일 형식, 스키마 | 설정 파일 형식, DB 스키마, API 구조 | +| **Deployment** | 배포 방식, 운영 절차, 배포 환경 | 컨테이너 배포, 스택 관리, 운영 가이드 | +| **Documentation** | 문서 작성, 가이드, 매뉴얼, 안내서 | 사용자 가이드, API 문서, 튜토리얼 | +| **Exception** | 오류 처리, 예외 복구, 재시도 전략 | 오류 복구, 검증 실패 처리, 폴백 전략 | +| **Installation** | 시스템 설치, 환경 구성, 초기화 절차 | Docker 이미지 빌드, DB 마이그레이션, 사전 조건 설정 | +| **Integration** | 외부 시스템 연동, 플러그인, 확장 | 3rd party 연동, 플러그인 인터페이스 | +| **Interface** | 사용자 상호작용 방식 (UI, API, CLI, 제어방식) | CLI 명령어, API 엔드포인트, 웹 UI 기능 | +| **Migration** | 데이터 이전, 버전 업그레이드 | 데이터 마이그레이션, 버전 호환성 | +| **Non-Functional** | 성능, 보안, 확장성, 호환성, 신뢰성 | 성능 목표, 보안 정책, 확장성 | +| **Testing** | 테스트 전략, QA 요구사항, 검증 방식 | 테스트 커버리지, 회귀 테스트, 수락 기준 | + +## Requirement 작성 규칙 +- 각 requirement는 고유 ID를 가진다. 예: `REQ-001` +- 다음 신규 requirement 번호의 source of truth는 이 문서의 `Next Requirement ID` 섹션이다. +- 새 requirement를 추가하거나 ID 충돌이 발생할 수 있는 변경을 했으면 `Next Requirement ID`를 함께 갱신한다. +- 각 requirement는 `Type`을 명시해야 한다. 위 분류 도표 중 정확하게 하나로 선택하며, `docs/srs//` 폴더명도 같은 문자열을 사용한다. +- 각 requirement는 `Intent`, `Requirement`, `Acceptance Criteria`, `Impacted Area`를 반드시 포함한다. +- 모호한 표현("개선한다", "적절히 처리한다") 대신 관찰 가능하고 test 가능한 문장을 사용한다. +- requirement 변경 사항은 해당 REQ 파일의 `Change Log`에 기록한다. +- requirement 변경 시 영향 받는 batch/release와 재검증 필요 여부를 `Change Log`에 남긴다. +- `Recent Change Log Summary`는 최신 5건만 유지한다. +- status 전환은 `Status Transition Evidence` 기준을 따른다. + +## Next Requirement ID + +- Current: `REQ-001` +- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다. + +## Requirement Register + +| ID | Title | Type | Status | Priority | Owner | Link | +| --- | --- | --- | --- | --- | --- | --- | + +## Recent Change Log Summary + +- 없음 \ No newline at end of file