- OQ-1: 구현 위치 (a′) 기존 슬롯 도메인 유지 + 운영 프로파일/규칙 추가
(PositionBook 신설 Out of Scope).
- OQ-2: safety_sell_enabled=false 인스턴스는 코어 손절매 미사용 — 보호 규칙
전략 모듈 전적 책임, 코어는 운영자 CLI exit 백스톱만 제공.
- OQ-3: watchdog per-instance timeout 연장(중장기 ≥1800s). 알림 연동은 후속 Discovery.
- OQ-4: 폴링/intent 주기 최소 1분~최대 10분 전제.
FR-2/범위/R-1/DECIDE 항목 동기화.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
slots RPC 응답에 available_slots: int|null 포함.
max_active_slots 미설정 시 null, 설정 시 max(0, M-active).
16 tests passed (AC-6 신규 3개 포함), 423 전체 통과.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
reconcile_universe 슬롯 생성 시 symbol 미저장 구현 누락을 AC-5로 추가.
Implemented 상태 유지 (기존 AC 1~4 evidence 유효).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
reconcile_universe 시그니처를 set[str] → dict[str, str] (portfolio_id→symbol)로 변경.
기존 symbol=NULL 슬롯은 다음 reconcile 실행 시 자동 backfill.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BAT-035/036 batch index: confirmed → release-candidate
- rel-006: BAT-035/036 추가, status confirmed, SHA 명시, smoke 한계·외부 소비자 분석 기술
- daemon.py: stale 주석 trex.snapshot.req → trex.slots.req
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BAT-032 (dcy-022): timeout_sec/slippage_pct 실행 정책, 미체결 자동 취소,
보호 지정가, `trex-core cancel` 백스톱. 마이그레이션 012.
BAT-033: `trex-core enter --qty` 필수 검증 — 미지정 시 RPC 전 즉시 오류.
BAT-034 (dcy-023): allocated_capital 죽은 필드 전 경로 제거 (domain·intent·
persistence·snapshot·CLI). 마이그레이션 013(비가역 DROP). 외부 발신자
unknown key 무시 수신 의미론 적용.
REL-006 confirmed: BAT-026~034 통합 릴리즈, pre-release smoke 증거 포함.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
new-discovery: 보유 자산 슬롯 수량 변경(HOLDING→HOLDING)·부분 매도·사이징 intent.
OQ-1~4 전부 결정 후 confirm-discovery 승인(Justin Ko):
- OQ-1 명령형 계약 — 전략이 cash+quantity 로 qty+price 계산·전송, core 는 실행 substrate(target 미저장·미추적)
- OQ-2 wire 단위 = 정수 주식 수+가격, 비중/금액 환산은 전략 책임
- OQ-3 증액 avg_price 가중평균·부분 매도 cost basis 유지·실현손익 ledger/hub 소유
- OQ-4 intent 당 1회 집행, core 측 target 저장·주기 reconcile 없음, 자동 리밸런싱 Out of Scope
- 부수: 과매도→min(intent,잔고)·이상이면 전량, 부분 체결→실제 체결만 ledger·미추적·전략 재수렴(증액/감액 대칭)
능동 capacity 배분·미체결 pending 고착 처분(issue #21)은 별도 Discovery 후보로 분리.
dcy-020 후속 참조 갱신 + index dcy-021 confirmed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
운영자 CLI 의 slots 조회 편의: --symbol, --slot-id 클라이언트 측 필터(--status 와
조합 가능) 추가. 두 필터 중 하나라도 주면 한 줄 요약 대신 슬롯 상세 블록
(status/symbol/portfolio_id/qty/avg_price/limit/allocated_capital/strategy_id/
sell_strategy_id/forced_close_at/universe_detached, holding 이면 watchdog)으로 출력.
필터 없으면 기존 terse 테이블 유지(무회귀).
구조/계약/런타임 흐름 영향 없는 표시 기능. tests/runtime/test_cli_operator.py
필터 4건 추가(24 passed), ruff clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
매수 계약 키를 portfolio_id → slot_id 로 이동(매도는 이미 slot_id). 외부 전략
무중단 위해 portfolio_id 레거시 dual-accept.
- BuyIntent: slot_id 필드 추가, portfolio_id Optional 완화
- _admit_buy: 자산 중심 모드 우선 분기; _admit_buy_asset_centric 가 slot_id(canonical)
또는 portfolio_id(legacy dual-accept)로 슬롯 해소, symbol 은 슬롯 portfolio_id 로 resolve.
unknown_slot/unknown_portfolio 사유 구분.
- messaging_handlers: buy 파싱에 slot_id 수용
- 신규 테스트: slot_id 매수 / unknown_slot / 기존 dual-accept 회귀
검증: 전체 389 passed / 36 skipped, ruff clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
config 게이트 이중 경로(max_active_slots 설정 시 자산 중심, 미설정 시 legacy pool).
운영 데몬은 cutover(BAT-δ) 전까지 pool 무중단.
- repository: find_slot_by_portfolio·count_active(holding+pending_buy+pending_sell)·
reconcile_universe(생성 멱등/soft-retire/tombstone, allow_retire 가드) — protocol+in_memory+PG
(PG: ON CONFLICT (instance_key, portfolio_id) WHERE portfolio_id IS NOT NULL)
- snapshot_scheduler: run_once swap 직후 _reconcile_slots(빈 universe skip, ≥50%↓ retire 보류)
- intents: _admit_buy 모드 분기 + _admit_buy_asset_centric(활성화/already_active/
capacity_full/unknown_portfolio/over-cap, 인스턴스 lock)
- daemon: instance_key·max_active_slots·reconcile_enabled·trading_date_fn 배선
- 신규 테스트: test_universe_reconcile(6), test_asset_centric_admission(6), PG reconcile(1)
검증: 단위 387 passed / 35 skipped, PG-gated 17 passed, ruff clean. legacy 무파손.
REQ-058/059/060 은 Approved 유지(자산 중심 경로 도입 검증; default 전환·cutover 는 BAT-δ).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
자산 중심 모드 게이트 + M 값. DaemonInstanceConfig/DaemonConfig 에
max_active_slots: Optional[int] 추가, from_toml 파싱(>0 검증), from_config 전파.
미설정(None) → legacy pool 모드. additive — 전체 375 passed, ruff clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
REQ-048/010 change-req. `--config` 를 이름으로 해석 + `--config-path <dir>`
(기본 ./config) + resolve_config_toml(슬래시 포함 값은 하위호환 명시 경로).
`.env` 를 config-dir 결정적 해석(--env-file 우선, 없으면 <config_dir>/.env,
CWD 무관) + config/.env.example + .gitignore config/* 허용목록. 운영자 CLI 도
--config-path/--env-file 동일 적용. from_env() legacy 루트 .env 폴백 유지로
완전 하위호환.
단위 23 + 전체 375 passed, ruff clean, 라이브 스모크(name·path 동일).
REQ-048/010 → Implemented.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
REL-002(BAT-009)·REL-003(BAT-010~013) 을 released→feedback-captured 로 전환해
REL-001/004 와 동일한 완료(종착) 상태로 정합. REL-002 Feedback Handoff 빈
플레이스홀더 정리(tooling 릴리즈, Discovery/REQ Input=없음). 포함 batch
BAT-009~013 release-candidate→released(register + 개별 index) — 누락 정정.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
issue #18(슬롯별 entry_count + closed 슬롯 재할당)을 Discovery 로 정리·확정.
OQ-1(entry_count=daily_slot 단독, daily_symbol_entries 와 분리)·OQ-2(tie-break:
entry_count→updated_at→slot_id)·OQ-3(closed 직접 후보, closed→pending_buy 신규
전이, →pending_buy 시 +1) 사용자 결정 반영. daily_symbol_entries 제거는 별도
REQ-002 change-req 트랙. confirm-discovery 게이트 통과 → confirmed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
trex-core enter 에 --forced-close-at <ISO8601>(절대시간) 옵션 추가.
지정 시 buy intent payload 의 기존 forced_close_at 에 매핑(계약·도메인·
forced-close 루프 REQ-037 불변, CLI 노출 갭만 보완). 잘못된 형식은 제출
전 거부, 미지정 시 미포함(하위호환). 상대시간 옵션은 미채택.
REQ-032 change-req(CHG-20260609-01/02) → BAT-024(batch-lite) →
Implemented. 단위 353 passed, ruff clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
릴리즈되지 않은 release-candidate 배치(BAT-022 슬롯 상태 가시화,
BAT-023 ledger 현금/포지션 write-back·option D)를 REL-004 범위에 추가.
확장 범위 증거(BAT-022 실 인프라 운영 재현, BAT-023 인프라 게이트
385 passed) 반영 후 confirm-release 게이트 통과 → Status confirmed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`trex-core slots` 가 snapshot RPC 의 universe `assets`(portfolio)를 슬롯 상태로
오인 표시하던 갭 정정. snapshot envelope 이 슬롯 상태를 운반하지 않아 발생
(10개 슬롯인데 universe 1개·status 없음 — BAT-007 HTTP 슬롯 read 제거 후
슬롯 상태 read 표면 부재가 근인).
- REQ-028 (CHG-20260608-01): snapshot envelope 에 read-only per-slot `slots[]`
additive 추가(AC-4). strategy `assets[]`(universe, no-price) 불변.
- REQ-032 (CHG-20260608-03): `_cmd_slots` 가 envelope `slots[]`(실제 슬롯 상태)
표시 + `--status` 를 슬롯 status 기준 client-side 필터 + watchdog 결합.
`universe` 는 `assets[]` 유지. `universe --json` 도 universe 데이터로 scope.
- canonical `portfolio.slot_to_dict` 단일화 — BAT-007 stub / BAT-008 envelope
두 경로가 동일 슬롯 스키마(외부명 `entry_price` 유지, dcy-012 호환).
- interface-contract 에 `slots[]` 계약 + `assets[]` vs `slots[]` 구분 반영.
검증: 단위 338 passed + ruff clean + 신규 코드 데몬으로 실 PostgreSQL/RabbitMQ
운영 재현 PASS(slots=10·status·DB 일치·universe 분리·비침습). REQ-028/032
Implemented, BAT-022 release-candidate. pytest 인프라 게이트는 Human Approval
Memo 수용(운영 재현이 실 경로 커버).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
데몬이 시스템 UTC 날짜로 슬롯을 1회만 preallocate 해 trading_date 가 KST 캘린더와
어긋나고 재시작 없이는 다음날 슬롯이 안 생기던 문제(issue #14) 정정.
거버넌스: 전부 change-req (신규 REQ 없음, dcy-014 OQ-3; 스케줄러는 REQ-030 패턴 준용).
- REQ-005: trading_date 를 설정 타임존(기본 Asia/Seoul) 기준 계산(timestamp 는 UTC
유지). DailyPreallocationScheduler 신규 — TZ 일자당 1회 멱등 fire, 재시작 없이
다음날 슬롯 자동 생성. setup() 배선 + trex-preallocation 스레드
- REQ-048: TOML trading_timezone/daily_preallocation_time 키 + from_config 전파
- REQ-009: runtime-flows/data-model 정합 + instance.example.toml
OQ-1 기본 00:00(TZ 자정, TOML 설정 가능) / OQ-2 매 캘린더일 생성(거래일 캘린더 후속).
멱등 preallocate 로 중복 tick·다중 인스턴스 중복 생성 0.
검증: 단위 302 passed/32 skipped, 인프라 게이트(PG+RabbitMQ) 334 passed, ruff clean.
신규 test_preallocation_scheduler(고정 clock) + test_instance_config 확장.
BAT-018 release-candidate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
배포 차단 아님 전제로 실 KIS 쓰기 경로 4가지 미검증을 Verification Checklist에 명시:
LIVE 체결→ledger 미실증, kill_switch LIVE 미실행, 실 2-인스턴스 동시기동 미검증,
거래일 성공 LIVE 주문 0건 + 운영 DB 최초 적용. + 배포 후 차기 거래일 실증 권고.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
## REQ-038 CHG-04/05: KIS 시세 tr_id 정정 (FHKST01010100)
- kis.py _tr_price(): TTTC8397R/VTTC8397R → FHKST01010100 (실전/모의 공용)
배포 전 실 KIS LIVE 진단에서 구 tr_id가 rt_cd=1 "없는 서비스 코드"로 거부됨을
확인 — stop-loss/take-profit이 LIVE에서 조용히 미발동하는 결함이었음.
FHKST01010100으로 정정 후 get_current_price('005930')=329000(rt_cd=0) 확인.
- test_kis_price.py: AC-7 테스트 정정 (FHKST01010100 공용 검증)
- REQ-038: CHG-04/05 Change Log 추가, Requirement/AC-7/Notes 정정
- BAT-011 implementation.md: LIVE 검증 및 tr_id 정정 이력 추가
- BAT-011 verification.md: AC-7 evidence를 CHG-04 정정 버전으로 갱신
- docs/srs/index.md: CHG-04/05 Change Log 항목 추가
## REL-003: core 자율 안전 매도 release 문서 생성
- docs/releases/rel-003_20260607_core-autonomous-safety-sell.md 신규 생성
(BAT-010 + BAT-011, app-service profile, Status: confirmed)
- docs/releases/index.md: REL-003 행 추가
## dcy-008: 비상 정지/강제 청산(kill-switch) Discovery 초안
- docs/discovery/dcy-008_20260607_emergency-stop-kill-switch.md 신규 생성
GitHub #3 기반; SlotService.sell() 재사용, 당일 전략 제외 day-scoped
FR 6개, NFR 3개, OQ 4개 (트리거 표면/영속 방식/수동 해제 결정 필요)
- docs/discovery/index.md: dcy-008 행 추가
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Record deployment evidence for REL-002 (tooling): bat-009 fast-forward
merged to main and pushed (ca75700..7b6ed55). No migration/restart;
broker=kis unaffected. Status confirmed -> released.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
REL-002 bundles BAT-009 (paper broker env tuning, REQ-010 AC-5) as a
tooling-profile release. Rollout/rollback/verification ready; status
confirmed. No DB migration or daemon restart; broker=kis runtime
unaffected (paper config only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bundle BAT-001~008 into REL-001 (app-service profile) and promote to
confirmed. Register index row added.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
REQ-017 CHG-20260606-01. Live portfolio-hub returned 404 for the
trex-orbit-assumed POST /v1/assets/{asset_id}/ledger/trades. Correct to
POST /v1/portfolios/{portfolio_id}/ledger/trades with body keys
quantity/fee_amount/tax_amount (was qty/fee/tax), success 201. Reverified
with live e2e (201 Created, outbox COMPLETED) + durability drain of the
prior 404'd item. Resolves the REL-001 ledger-write release blocker.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Align REQ-027 and BAT-008 verification/design with the live portfolio-hub
API discovered during release prep: whoami via /v1/user_info, {portfolios}
envelope, client-side managed_by_daemon_id filter, http:// scheme default,
and strategy fields deferred (None/{}). Records the re-verification evidence
(new contract tests + live e2e) so BAT-008 can bundle into the first release
with non-stale verification. REQ-027 stays Implemented.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Record that the first strategy (orb-v1) queries view=buyable without a
strategy_key, so missing PortfolioItem strategy fields are harmless for the
single-strategy stage. Documentation-only; REQ-029 stays Implemented.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
whoami now hits GET /v1/user_info (the live endpoint; /v1/auth/whoami
does not exist), get_portfolios parses the {portfolios:[...],total} envelope
and filters by managed_by_daemon_id client-side (the list endpoint is
token-scoped, no such query param), and a missing URL scheme now defaults
to http:// so a bare host can't silently degrade the daemon.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- new-discovery dcy-005: read-direction follow-up of dcy-004 (deferred
get_assets/get_portfolios). trex-core exposes portfolio-hub asset snapshot
as a read API, returning buy candidates with slot-occupied symbols filtered
out (slot overlay) and an empty list when no slots remain.
- 6 open questions pinned: snapshot shape, freshness/cache, core-proxy policy,
in-flight overlay (ledger outbox eventual consistency), availability degrade,
empty-list semantics.
- Link dcy-004 후속 Discovery 참조 → dcy-005; add dcy-005 to discovery index.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Record fills to the portfolio-hub ledger (orbit post_ledger_trade pattern)
so external accounting/positions reflect trades. The slot already carries
portfolio_id but nothing consumes it; this closes a deferral not previously
made explicit in dcy-003. Scope: LedgerPort + portfolio-hub adapter + stub,
record on buy/sell fill, execution_id idempotency, failure retry/hold;
out of scope: non-trade transactions, asset sync, reconciliation. OQ-1
(asset_id source), OQ-2 (durability), OQ-3 (exec data source) left for
confirm-discovery; handoff held.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port the trex-orbit Redis token-cache pattern so the KIS access token
survives daemon restarts and is shared across processes, avoiding KIS
token-issuance rate limits. KISBroker._ensure_token now resolves L1
in-memory -> L2 cache -> issue, storing issued tokens back to the cache.
- adapters/broker/token_cache.py: TokenCache protocol + RedisTokenCache
(key trex:broker:kis:{account_ref}:token, token+expiry+app_key suffix
JSON, ex=ttl, best-effort with graceful fallback) + InMemoryTokenCache.
- kis.py: optional token_cache injection.
- runtime config/daemon: TREX_KIS_REDIS_URL wires a RedisTokenCache.
- pyproject: redis>=5.
Verification: 96 passed, ruff clean — cache hit avoids issuance, cache is
shared across instances (restart/multi-process survival), backend errors
fall back to issuance (no regression), and app_key-suffix mismatch
invalidates a stale cache. Tested deterministically with an in-memory
double (no Redis server required). Processed via the minor-change fast
path: REQ-016 -> Implemented, BAT-005 (batch-lite) -> release-candidate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dcy-003 confirmed (all OQ answered, operator-confirmed scope/risk):
- OQ-1: paper/stub + real KIS Open API adapter (validated on KIS paper
server; live account go-live config-gated, deferred).
- OQ-2: unified async fill (submit -> poll); paper is a deterministic
async double (no synchronous shortcut) for faithful path coverage.
- OQ-3: option A — pending slot is the execution queue, broker_order_id
is the idempotency guard; no separate outbox table (option B as a
growth hook; intent_log stays dedup-only).
- OQ-4: dedicated background execution loop (claim -> submit -> poll ->
reconcile); intent API only transitions to pending.
Decompose into REQ-011~015 (all Proposed): BrokerPort + paper double,
KIS adapter, execution loop, durability+reconciliation (Exception),
baseline alignment. NFR-1/2/3 absorbed. Update SRS index + dcy-003
created-REQ refs. Safety floor, KIS live account, strategy daemons, and
auth remain deferred to follow-up Discoveries.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
DaemonConfig.from_env() now best-effort loads a .env file (find_dotenv
usecwd, load_dotenv override=False) so operators can manage daemon env
vars via .env, with real OS env taking precedence. Add python-dotenv
dependency, gitignore .env, ship .env.example, and add config tests
(load / OS-env precedence / absence regression / missing-DSN guard).
Verification: 78 passed, ruff clean, .env ignored + .env.example tracked,
and a .env-only DaemonConfig smoke. Processed via the minor-change fast
path: REQ-010 (Configuration) -> Implemented, BAT-003 (batch-lite,
no design) -> release-candidate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implement REQ-005~009 (dcy-002 slice 1) as an onion stack on top of the
BAT-001 pure domain:
- application: IntentService (admission + single-writer transition +
intent_id idempotency via durable intent_log)
- adapters/persistence: PostgreSQLSlotRepository + PostgreSQLIntentStore +
trex-core-owned migrations (daily_slot per Appendix A, daily_symbol_entries,
slot_transition_log, intent_log) + in-memory intent store
- adapters/api: FastAPI /v1 (healthz, intents/buy|sell|{id}, slots, capacity)
- runtime: trex-core-daemon entrypoint with lifespan migrate+preallocate
Verification (against local PostgreSQL 18): 74 passed, ruff clean, domain
import sweep shows zero web/db deps (NFR-1), 20-thread concurrency admits
exactly the idle count (NFR-2), idempotent resubmit causes no double
transition (NFR-3), EXPECTED_SLOT_FIELDS<->information_schema drift test
(realizes dcy-001 OQ-2's deferred DB-side check), and a daemon E2E smoke.
Align all four baseline docs to the new daemon/API/persistence layers.
BAT-002 -> release-candidate; REQ-005~009 -> Implemented. Full async outbox,
broker execution, safety floor, and strategy daemons remain deferred to a
follow-up Discovery.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>