feat(execution,obs): 호가단위 스냅(dcy-030/#28) + 운영 관측성(dcy-029/#29) + REL-007 환류

dcy-030 (issue #28, P0 체결 복구):
- REQ-083 KRX 호가단위(tick) 순수 유틸 (domain/pricing.py)
- REQ-070 CHG: 슬리피지 실효가 호가단위 스냅 — 상한 준수(매수 floor/매도 ceil)
  + band<1tick 하한/상한 보장 + 부동소수 epsilon 가드. 147700→148400/54500→54700.
- BAT-044 release-candidate

dcy-029 (issue #29, 운영 관측성):
- REQ-084 구조화 로깅 기반 (runtime/logging_setup.py): ISO8601 KST·레벨·Loki JSON
  ·correlation id(slot_id)
- REQ-085 주문 결과 로깅 (event=order_submit|fill|reject)
- REQ-087 거부 ERROR 가시성 (조용한 롤백 제거)
- REQ-086 청산 reason+actor 동반 노출 (안전망/전략 구분, 신규 필드 없음)
- REQ-088 운영 조회 CLI report (application/operator_report.py, 보유·오늘 체결
  ·실현 PnL net·대기, direct-DB)
- REQ-089 운영자 런북 docs/operations.md
- REQ-090 baseline 정합 (runtime-flows·project-structure·interface-contract)
- BAT-045(P0)·BAT-046(P1) release-candidate

REL-007: confirmed → feedback-captured (운영 인스턴스 라이브 검증 + #28/#29 환류
정규화). BAT-037~041 released.

검증: 537 passed, 47 skipped, 회귀 0, ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 13:19:31 +09:00
co-authored by Claude Opus 4.8
parent e0d4e71304
commit d8d9021260
48 changed files with 2461 additions and 58 deletions
@@ -0,0 +1,54 @@
# req-089: 운영자 런북 — docs/operations.md 신설
- Status: Implemented
- Type: Documentation
- Priority: Medium
- Owner: project maintainers
## Intent
- trex-core에 사람 운영자용 문서(배포·디버깅·CLI 사용법)가 없다. 운영 런북 `docs/operations.md`를 신설해 신규 운영자가 배포·실행, 상태/PnL 조회, 거부·미체결 디버깅을 그 문서만으로 수행하게 한다. (dcy-029 FR-8)
## Requirement
- `docs/operations.md`를 신설하고 최소 4영역을 포함한다:
1. **배포/실행**: 필수 env(`TREX_POSTGRESQL_DSN`/`TREX_RABBITMQ_URL`/`TREX_BROKER` 등), `--config`/`--env-file`, 기동·종료, 테스트 DB 안전 절차.
2. **운영자 CLI 사용법**: `pause/resume/slots/universe/enter/exit/cancel` + 신설 조회/PnL 서브커맨드(REQ-088).
3. **로깅/관측성 사용법**: 타임스탬프·레벨, 주문 결과 로그 grep(`event=order_submit|fill|reject`), `TREX_LOG_FORMAT=json`/Loki·correlation id, 청산 reason+actor 해석(REQ-086).
4. **디버깅/트러블슈팅**: 거부 ERROR 확인, 미체결 진단, DB 상태 조회(daily_slot/ledger_outbox), 자주 겪는 증상→원인→조치.
- 기존 `.claude/skills/run-trex-core-daemon/SKILL.md`의 사실 자료(env 표·launch·troubleshooting)를 사람용 문서로 추출·정리하고, 본 반복(REQ-084~088) 관측성 기능 사용법을 반영한다.
## Acceptance Criteria
1. Given docs/operations.md, When 확인, Then 배포/실행 절차(env·config·기동·종료)가 포함돼 있다.
2. Given 운영자 CLI 절, When 확인, Then 기존 서브커맨드 + 신설 조회/PnL(REQ-088) 사용법이 있다.
3. Given 로깅/관측성 절, When 확인, Then 타임스탬프·주문결과 grep·JSON/Loki·correlation id·reason+actor 해석이 있다.
4. Given 디버깅 절, When 확인, Then 거부 ERROR 확인·미체결 진단·DB 조회 가이드가 있다.
5. Given 신규 운영자, When 런북만 참고, Then 데몬 배포·CLI 조회·거부 디버깅을 수행할 수 있다(4영역 모두 충족).
## Impacted Area
- Docs: docs/operations.md(신설), 참조: .claude/skills/run-trex-core-daemon/SKILL.md
- Modules: 없음(문서)
- Tests: 없음(문서 — verification은 4영역 포함 리뷰 체크)
## Notes
- 본 REQ는 REQ-084~088 구현 사용법을 문서화하므로 그 REQ들과 같은 batch(P1) 후반에 작성한다.
- 출처: dcy-029 FR-8.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-8로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-046 release-candidate, dcy-029 P1). 근거: 단위/문서 AC 매핑(REQ-086 reason+actor 로그·interface-contract; REQ-088 operator_report 집계·net PnL·KST 경계·CLI report; REQ-089 docs/operations.md 4영역; REQ-090 runtime-flows·project-structure 정합). 14 passed(report+safety_sell), 전체 537 passed/47 skipped 회귀 0, ruff clean. report direct-DB·Loki 실 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -0,0 +1,54 @@
# req-090: 관측성 baseline 문서 정합 — 로깅/관측성·PnL 조회 흐름
- Status: Implemented
- Type: Documentation
- Priority: Medium
- Owner: project maintainers
## Intent
- dcy-029가 런타임 로깅·청산 분류·PnL 조회 흐름을 바꾸므로 baseline 문서를 실제 구현과 정합시킨다. (dcy-029 FR-6)
## Requirement
- `docs/runtime-flows.md`에 다음 흐름을 추가/갱신한다:
- 구조화 로깅 기반(ISO8601 KST 타임스탬프·레벨·JSON/Loki·correlation id, REQ-084).
- 주문 결과 로깅(submit/fill/reject 일관 라인, REQ-085) 및 거부 ERROR 가시성(REQ-087).
- 청산 reason+actor 동반 노출(REQ-086).
- 운영자 조회 CLI(보유/오늘 체결/실현 PnL/대기 주문, REQ-088).
- `docs/project-structure.md`에 신규 로깅 모듈(REQ-084) 책임을 반영한다.
- baseline 문서는 전체 흐름을 복제하지 않고 구현된 제약·진입점만 정합 수준으로 기술한다.
## Acceptance Criteria
1. Given runtime-flows.md, When 갱신 후, Then 구조화 로깅·correlation id 흐름이 기술돼 있다.
2. Given runtime-flows.md, When 갱신 후, Then 주문 결과 로깅·거부 ERROR·청산 reason+actor·PnL 조회 CLI가 기술돼 있다.
3. Given project-structure.md, When 갱신 후, Then 신규 로깅 모듈이 모듈 트리에 반영돼 있다.
4. Given baseline 문서, When 확인, Then 실제 구현(REQ-084~088)과 모순이 없다.
## Impacted Area
- Docs: docs/runtime-flows.md, docs/project-structure.md
- Modules: 없음(문서)
- Tests: 없음(문서 — verification은 정합 리뷰)
## Notes
- 본 REQ는 P1 batch 구현 완료 후 정합한다(REQ-084~088 결과 반영).
- 출처: dcy-029 FR-6.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-6로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-046 release-candidate, dcy-029 P1). 근거: 단위/문서 AC 매핑(REQ-086 reason+actor 로그·interface-contract; REQ-088 operator_report 집계·net PnL·KST 경계·CLI report; REQ-089 docs/operations.md 4영역; REQ-090 runtime-flows·project-structure 정합). 14 passed(report+safety_sell), 전체 537 passed/47 skipped 회귀 0, ruff clean. report direct-DB·Loki 실 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -9,25 +9,30 @@
- `slippage_pct` 가 지정된 주문을 dispatch 할 때 `entry_price*(1±pct)` 실효 지정가로 제출해 과도한 불리 체결을 막는다. `entry_price` 없으면 무시(순수 시장가는 슬리피지 기준 없음). (dcy-022 FR-3)
## Requirement
- `_dispatch` 가 슬롯의 `slippage_pct` 를 읽어 실효 지정가를 산출한다: 매수 = `limit_price * (1 + slippage_pct/100)` (올림, ceil), 매도 = `limit_price * (1 - slippage_pct/100)` (내림, floor). `limit_price`(= `entry_price`)가 None 이면 `slippage_pct` 를 무시하고 시장가 주문 제출(기존 동작 보존). KRX 호가단위 반올림은 체결 보장 방향(매수=상위 단위, 매도=하위 단위)으로 적용한다(단, 테스트에서는 간단한 int() 사용 가능 — 정밀 호가단위 테이블은 후속). `slippage_pct` 없는 슬롯은 기존 `limit_price` 직접 사용(회귀 없음).
- `_dispatch` 가 슬롯의 `slippage_pct` 를 읽어 실효 지정가를 산출한 뒤 **KRX 호가단위(REQ-083)로 스냅**한다. 방향은 **상한 준수**: 매수 = `floor_to_tick(limit_price * (1 + slippage_pct/100))` (내림 — slippage 상한 미초과), 매도 = `ceil_to_tick(limit_price * (1 - slippage_pct/100))` (올림 — 매도 하한 미초과). band<1tick 엣지에서 미체결을 막기 위해 하한/상한을 보장한다: 매수 실효가 = `max(floor_to_tick(...), ceil_to_tick(limit_price))`, 매도 실효가 = `min(ceil_to_tick(...), floor_to_tick(limit_price))`. `limit_price`(= `entry_price`)가 None 이면 `slippage_pct` 를 무시하고 시장가 주문 제출(기존 동작 보존, 스냅 없음). `slippage_pct` 없는 슬롯은 기존 `limit_price` 직접 사용(회귀 없음). 주식 전용 — ETF/ETN 비주식 호가체계는 범위 밖(dcy-030 OQ-1).
## Acceptance Criteria
1. Given 슬롯에 `limit_price=10000`, `slippage_pct=1.0`, side=buy, When dispatch, Then OrderRequest.limit_price = `ceil(10000*1.01)` = 10100.
2. Given 슬롯에 `limit_price=10000`, `slippage_pct=1.0`, side=sell, When dispatch, Then OrderRequest.limit_price = `floor(10000*0.99)` = 9900.
3. Given `limit_price=None`(시장가), `slippage_pct=1.0`, When dispatch, Then OrderRequest.limit_price = None(시장가 — slippage 무시).
1. Given 슬롯에 `limit_price=10000`, `slippage_pct=1.0`, side=buy, When dispatch, Then OrderRequest.limit_price = `floor_to_tick(10000*1.01)` = `floor_to_tick(10100)` = 10100 (상한 준수 내림).
2. Given 슬롯에 `limit_price=10000`, `slippage_pct=1.0`, side=sell, When dispatch, Then OrderRequest.limit_price = `ceil_to_tick(10000*0.99)` = `ceil_to_tick(9900)` = 9900 (하한 준수 올림).
3. Given `limit_price=None`(시장가), `slippage_pct=1.0`, When dispatch, Then OrderRequest.limit_price = None(시장가 — slippage·스냅 무시).
4. Given `slippage_pct=None`, `limit_price=10000`, When dispatch, Then OrderRequest.limit_price = 10000(기존 동작, 회귀 없음).
5. Given `slippage_pct=0.0`, When dispatch, Then 실효 지정가 = limit_price(0% 슬리피지 = 기준가 그대로).
5. Given `slippage_pct=0.0`, When dispatch, Then 실효 지정가 = `floor_to_tick(limit_price)`(0% 슬리피지 = 기준가의 유효 호가).
6. Given 기존 매수/매도 슬롯(slippage_pct 없음), When dispatch, Then 기존 동작과 동일(전체 회귀 없음).
7. Given `limit_price=147700`, `slippage_pct=0.5`, side=buy, When dispatch, Then `floor_to_tick(148438.5)` = 148400 (issue #28 케이스, 유효 호가·상한 미초과).
8. Given `limit_price=54500`, `slippage_pct=0.5`, side=buy, When dispatch, Then `floor_to_tick(54772.5)` = 54700 (issue #28 케이스).
9. Given band<1tick (예: `limit_price=147700`, `slippage_pct=0.01`, buy), When dispatch, Then 매수 실효가 = `max(floor_to_tick(147714.77), ceil_to_tick(147700))` ≥ entry 유효 호가 (미체결 방지), 그리고 slippage 상한 미초과.
10. Given 임의 매수/매도 + slippage, When dispatch, Then 결과는 유효 KRX 호가단위 배수이고 매수 ≤ `limit*(1+pct/100)` / 매도 ≥ `limit*(1-pct/100)`.
## Impacted Area
- Docs: docs/runtime-flows.md(slippage dispatch 흐름)
- Modules: trex_core/application/execution.py(`_dispatch` slippage 계산)
- Tests: tests/application/test_execution.py(slippage dispatch 단위)
- Docs: docs/runtime-flows.md(slippage dispatch + 호가단위 스냅 흐름), docs/project-structure.md(신규 tick 유틸 — REQ-083)
- Modules: trex_core/application/execution.py(`_dispatch` slippage 계산 + 호가단위 스냅), REQ-083 tick 유틸 소비
- Tests: tests/application/test_execution.py(slippage dispatch + 스냅 방향·경계·band<tick 하한 보장 단위)
## Notes
- `entry_price` = `limit_price` 로 슬롯에 저장되는 설계를 그대로 사용(REQ-013 CHG-20260608-01 선례). 슬리피지는 dispatch-time 변환만 — 슬롯의 `limit_price` 자체를 덮어쓰지 않는다.
- KRX 정밀 호가단위 반올림(500원 미만 → 1원, 500~2000 → 5원 등)은 후속 주기. 현재 구현은 int(math.ceil/floor) 로 충분(테스트 범위 내).
- 출처: dcy-022 FR-3, OQ-2.
- (CHG-20260616-01, dcy-030) KRX 정밀 호가단위 스냅을 REQ-083 유틸로 구현. 반올림 방향 = 상한 준수(매수 내림/매도 올림). 원래 메모의 "체결 보장(매수 상위/매도 하위)" 방향에서 전환 — `slippage_pct`를 리스크 상한으로 취급하기 때문(상한 1틱 초과 방지). band<1tick 하한/상한 보장으로 미체결 방지.
- 주식 전용. ETF/ETN 비주식 호가체계 및 2,000원 미만 비주식은 미지원(dcy-030 OQ-1, known limitation).
- 출처: dcy-022 FR-3, OQ-2 / dcy-030 FR-2·2b·3·4.
## Change Log
@@ -87,3 +92,52 @@
- Author: Justin Ko
- Type: status
- Summary: Approved → Implemented (confirm-req-implemented). 근거: BAT-032(release-candidate) verification — 실행 정책(timeout_sec·slippage_pct) 계약·집행·운영자 cancel 백스톱 전 AC acceptance mapping 존재(신규 71 tests), 단위 425 passed 회귀 없음, baseline 2문서 수동 확인(M5). Blocking Issues 없음.
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- slippage 실효 지정가에 **KRX 호가단위 스냅**을 추가하고, 반올림 방향을 원래 메모의 "체결 보장(매수=상위/매도=하위)"에서 **"상한 준수(매수=하위/매도=상위)"** 로 전환한다. band<1tick 엣지에 하한(매수)/상한(매도) 보장을 추가한다. (dcy-030 FR-2/FR-2b/FR-3/FR-4)
#### Intent
- 현재 구현은 `int(ceil/floor)`만 적용하고 KRX 호가단위로 스냅하지 않아, slippage_pct>0인 매수 한계가가 호가단위를 위반해 KIS `주식주문호가단위 오류`로 전량 거부됨(issue #28). 호가단위 스냅으로 거부를 제거하되, `slippage_pct`를 리스크 상한으로 취급해 스냅이 상한을 넘기지 않도록 매수=내림/매도=올림으로 정정한다.
#### Acceptance Criteria Delta
- Updated:
- AC-1: 매수 = `floor_to_tick(limit*(1+pct/100))` (상한 준수 내림). 예: `limit=10000,pct=1.0` → `floor_to_tick(10100)=10100`.
- AC-2: 매도 = `ceil_to_tick(limit*(1-pct/100))` (하한 준수 올림). 예: `limit=10000,pct=1.0` → `ceil_to_tick(9900)=9900`.
- Added:
- AC-7: `limit=147700,pct=0.5,buy` → `floor_to_tick(148438.5)=148400` (issue #28 케이스).
- AC-8: `limit=54500,pct=0.5,buy` → `floor_to_tick(54772.5)=54700` (issue #28 케이스).
- AC-9 (band<1tick 하한 보장): 매수 실효가 = `max(floor_to_tick(limit*(1+pct/100)), ceil_to_tick(limit))`; 매도 실효가 = `min(ceil_to_tick(limit*(1-pct/100)), floor_to_tick(limit))`. slippage<1tick이어도 최소 entry 유효 호가 보장.
- AC-10: 스냅 결과는 항상 유효 호가단위 배수이고, 매수 ≤ `limit*(1+pct/100)` / 매도 ≥ `limit*(1-pct/100)` (상한·하한 미초과).
- Removed:
- (없음 — AC-3·4·5·6 시장가/무slippage/0% 회귀 기준 유지)
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md(주문 집행 슬리피지 dispatch에 호가단위 스냅 단계 추가), docs/project-structure.md(신규 tick 유틸 — REQ-083)
- Modules:
- trex_core/application/execution.py(`_dispatch` 스냅 적용), REQ-083 tick 유틸 소비
- Tests:
- tests/application/test_execution.py(슬리피지 스냅 방향·경계·band<tick 하한 보장), REQ-083 tick 단위 테스트
#### Delivery Trace Delta
- Batches: BAT-032(REQ-070 최초 구현) — 본 변경은 신규 batch(dcy-030)에서 재구현·재검증.
- Releases: REL-006(BAT-032 released) — 운영 영향(매수 거부 해소)은 dcy-030 batch 배포 시 신규 release로 추적.
#### Revalidation Impact
- Reverification Needed: yes
- Existing Implementation Invalidated: yes (tick 스냅 부재 → 매수 거부; 반올림 방향도 변경)
- Status Recommendation: revert-to-approved
- Follow-up Action: dcy-030 batch에서 REQ-083 + REQ-070 재구현·검증 후 confirm-req-implemented로 재전환.
#### Validation Plan
- REQ-083 tick 유틸 단위 + execution.py 슬리피지 스냅 방향/경계/band<tick 하한 보장 단위 + 기존 AC-3~6 회귀.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-044 release-candidate, dcy-030/issue #28). 근거: `execution.py` `_dispatch` 호가단위 스냅 구현(상한 준수 매수 floor/매도 ceil + band<tick 보장 + epsilon 가드, REQ-083 소비). AC-1·2·5·7·8·9·10 단위 매핑(issue #28 케이스 147700→148400/54500→54700, 35000@0.7%→35200, band<tick), AC-3·4·6 회귀. 47 passed(pricing+execution_policy), 전체 516 passed/47 skipped 회귀 0, ruff clean. Blocking Issues 없음.
@@ -0,0 +1,61 @@
# req-083: KRX 호가단위(tick) 산출 유틸 — 가격→tick 순수 함수 + 배수 내림/올림
- Status: Implemented
- Type: Integration
- Priority: High
- Owner: project maintainers
## Intent
- 가격대별 KRX 주식 호가단위(2023.1.25~)를 산출하는 순수 함수와 tick 배수 내림/올림 헬퍼를 제공해, slippage 보호 지정가 스냅(REQ-070)과 이후 호가단위가 필요한 지점이 단일 검증된 유틸을 재사용하게 한다. (dcy-030 FR-1)
## Requirement
- 가격(int/float, 원) → 해당 가격대의 KRX 주식 호가단위(tick, int)를 반환하는 순수 함수를 제공한다. 구간표(2023.1.25~):
- `< 2,000` → 1
- `2,000 ≤ p < 5,000` → 5
- `5,000 ≤ p < 20,000` → 10
- `20,000 ≤ p < 50,000` → 50
- `50,000 ≤ p < 200,000` → 100
- `200,000 ≤ p < 500,000` → 500
- `≥ 500,000` → 1,000
- 가격을 해당 tick의 **내림 배수**(`floor_to_tick`)와 **올림 배수**(`ceil_to_tick`)로 정규화하는 순수 헬퍼를 제공한다. 결과는 항상 tick의 정수배다.
- 구간 경계는 하한 포함/상한 미만(`[lo, hi)`)으로 처리한다(예: 정확히 50,000원은 100원 tick).
- 주식 전용이다. ETF/ETN 등 비주식 호가체계는 이번 범위 밖이며(dcy-030 OQ-1), 종목 유형 분기는 두지 않는다(known limitation: 2,000원 미만 비주식은 미지원).
## Acceptance Criteria
1. Given 가격 1,500, When tick 산출, Then 1.
2. Given 가격 3,000 / 12,000 / 35,000 / 147,700 / 300,000 / 800,000, When tick 산출, Then 각각 5 / 10 / 50 / 100 / 500 / 1,000.
3. Given 경계값 2,000 / 5,000 / 20,000 / 50,000 / 200,000 / 500,000, When tick 산출, Then 각각 5 / 10 / 50 / 100 / 500 / 1,000 (하한 포함).
4. Given 가격 148,439, When `floor_to_tick`, Then 148,400 (tick 100의 내림 배수).
5. Given 가격 54,773, When `floor_to_tick`, Then 54,700; When `ceil_to_tick`, Then 54,800.
6. Given 임의 가격 p, When `floor_to_tick(p)`/`ceil_to_tick(p)`, Then 결과는 tick(p)의 정수배이고 `floor ≤ p ≤ ceil`.
## Impacted Area
- Docs: docs/runtime-flows.md(주문 집행 슬리피지 스냅 단계 — REQ-070 change와 공동), docs/project-structure.md(신규 tick 유틸 모듈 책임)
- Modules: 신규 순수 모듈(후보: `trex_core/domain/pricing.py` 또는 `trex_core/application/tick_size.py` — design에서 확정), REQ-070 dispatch에서 소비
- Tests: 신규 단위 테스트(각 가격 구간 경계값 + floor/ceil 불변식)
## Notes
- 출처: dcy-030 FR-1, OQ-1(주식 전용).
- tick 표는 단일 상수 테이블로 모아 KRX 제도 변경 시 변경 지점을 1곳으로 한다(dcy-030 R-3).
- 모듈 배치는 순수 함수이므로 domain 계층 후보. 정확한 위치는 batch design에서 확정.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-030 FR-1로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC(경계값 6 + floor/ceil 불변식) 충족, source dcy-030(confirmed, Open OQ 0) 정합. REQ-070 change-req와 함께 dcy-030 단일 batch 편성 예정.
### CHG-20260616-03
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-044 release-candidate, dcy-030). 근거: `trex_core/domain/pricing.py` 구현 + `tests/domain/test_pricing.py` 전 AC 매핑(대표값/경계값/floor·ceil 불변식). 47 passed(pricing+execution), 전체 516 passed/47 skipped 회귀 0, ruff clean. Blocking Issues 없음.
@@ -0,0 +1,56 @@
# req-085: 주문 결과 로깅 — submit/체결/거부 일관 tailable 로그
- Status: Implemented
- Type: Integration
- Priority: High
- Owner: project maintainers
## Intent
- 주문 결과(체결/거부)가 산발적 로그·DB(`slot_transition_log`)에만 남아 호가단위 거부(#28)를 수 시간 못 봤다. 모든 주문 submit과 그 결과(체결가·수량·수수료·세금, 또는 거부+사유)를 타임스탬프 달린 **일관(tailable) 로그 라인**으로 출력해 `grep`/`tail`로 당일 체결·거부를 즉시 전수 추출할 수 있게 한다. (dcy-029 FR-2)
## Requirement
- 집행 루프(`execution.py`)의 주문 dispatch/poll 경로에서 다음 이벤트를 일관된 안정적 키를 가진 한 줄 로그로 남긴다:
- **submit**: side, symbol, slot_id, qty, limit_price(또는 시장가), order_type.
- **fill**: side, symbol, slot_id, 체결가, 체결수량, fee, tax.
- **reject**: side, symbol, slot_id, 거부 사유.
- 로그 라인은 안정적 키(예: `event=order_submit|order_fill|order_reject`, `symbol=`, `slot_id=`)를 포함해 grep 필터가 가능해야 한다. JSON 포맷(REQ-084) 시 동일 필드가 구조화 키로 나간다.
- correlation id(REQ-084)가 설정돼 있으면 submit/fill/reject 로그가 같은 id를 공유한다.
- 기존 슬롯 전이/원장 기록 동작은 변경하지 않는다(로그 추가만, additive).
## Acceptance Criteria
1. Given 매수 주문 dispatch, When submit, Then `event=order_submit` + side/symbol/slot_id/qty/limit_price를 포함한 한 줄 로그가 남는다.
2. Given 체결, When poll fill, Then `event=order_fill` + 체결가/체결수량/fee/tax를 포함한 로그가 남는다.
3. Given 거부, When poll/ dispatch reject, Then `event=order_reject` + 사유를 포함한 로그가 남는다.
4. Given `TREX_LOG_FORMAT=json`, When 위 이벤트, Then 해당 키들이 JSON 구조화 필드로 출력된다.
5. Given 일련의 체결/거부, When `grep "event=order_reject"`, Then 당일 거부 주문을 전수 추출할 수 있다.
6. Given correlation id 설정 컨텍스트, When submit→fill, Then 두 로그가 동일 correlation id를 가진다.
## Impacted Area
- Docs: docs/runtime-flows.md(주문 집행 루프 — 결과 로깅)
- Modules: trex_core/application/execution.py(`_dispatch`/`_poll`/`_on_filled`/`_rollback` 로깅), REQ-084 로깅 기반 소비
- Tests: tests/application/test_execution* (submit/fill/reject 로그 caplog 단위)
## Notes
- FR-4(거부 ERROR 레벨)는 REQ-087에서 다룬다. 본 REQ는 submit/fill/reject의 **일관 구조·가시성**(레벨 무관)에 집중하되, reject 로그 라인은 REQ-087과 동일 지점에서 협조한다.
- 출처: dcy-029 FR-2.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-2로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-045 release-candidate, dcy-029 P0). 근거: 단위 AC 매핑(logging_setup text/json/KST/cid/idempotent, execution 주문 결과 submit/fill/reject + cid=slot_id + 거부 ERROR). 35 passed(logging+execution_policy), 전체 529 passed/47 skipped 회귀 0, ruff clean. 실 Loki 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -0,0 +1,53 @@
# req-086: 청산 reason+actor 동반 노출 — 안전망/전략 구분 가시화
- Status: Implemented
- Type: Interface
- Priority: Medium
- Owner: project maintainers
## Intent
- watchdog 소유 안전망 청산이 `reason=stop_loss`로만 보여 "전략의 진짜 손절"로 오해됐다(2026-06-15 064400). 신규 필드 없이, 기존 `reason`(조건축)과 기존 `actor`(주체축)를 **함께** 노출해 "안전망 자율청산(actor=safety_sell)"과 "전략 손절(actor=strategy)"을 운영자가 구분하게 한다. (dcy-029 FR-3, OQ-4=Option A)
## Requirement
- 기존 `reason` 어휘 `{stop_loss, take_profit, forced_close_at, market_close_liquidation}`(safety_sell 발화)와 전략 SellIntent의 reason을 계약으로 고정한다(신규 reason 값·신규 분류 필드 없음).
- 슬롯 전이 로그/이벤트/조회 뷰에 `reason`과 `actor`(`safety_sell`/`strategy`/`execution_loop`)를 **함께** 노출한다. 특히 주문 결과 로깅(REQ-085)·조회 CLI(REQ-088)·청산 로그에 actor가 reason과 같이 보이도록 한다.
- `docs/interface-contract.md`에 reason+actor 어휘와 "안전망 자율청산 family vs 전략 매도" 구분을 명문화한다.
- 기존 `slots.req`/이벤트/전이 기록의 기존 동작은 깨지 않는다(additive 노출).
## Acceptance Criteria
1. Given safety_sell이 stop_loss로 발화, When 전이/로그, Then `reason=stop_loss` + `actor=safety_sell`이 함께 기록된다.
2. Given 전략 SellIntent 매도, When 전이/로그, Then `actor`가 전략 주체로 기록되어 안전망과 구분된다.
3. Given 청산 로그 라인, When 운영자가 확인, Then reason만으로 오해되지 않도록 actor가 동반 노출된다.
4. Given safety_sell 4경로(stop_loss/take_profit/forced_close_at/market_close_liquidation), When 발화, Then 각 reason이 actor=safety_sell과 함께 정확히 기록된다.
5. Given 기존 reason 소비처(`_SELL_REJECT_RETRYABLE` 등), When 변경 적용, Then 기존 동작 회귀 없음(reason 값 불변).
6. Given interface-contract.md, When 갱신 후, Then reason+actor 어휘와 구분 규칙이 문서화돼 있다.
## Impacted Area
- Docs: docs/interface-contract.md(reason+actor 어휘), docs/runtime-flows.md(청산 분류 노출)
- Modules: trex_core/application/safety_sell.py·execution.py(로그에 actor 동반), 조회 뷰(REQ-088)·주문결과 로깅(REQ-085)과 협조. `slot_transition_log`는 이미 actor 기록.
- Tests: safety_sell 각 경로 reason·actor 단위, 노출 형식 단위
## Notes
- 코드 확인: `slot_transition_log`는 이미 `actor`를 기록하고, safety_sell은 이미 구분된 reason으로 발화한다. 본 REQ는 둘을 **함께 노출**(로그/뷰/계약 문서)하는 가시화가 핵심이며 신규 필드·신규 reason 값은 만들지 않는다(dcy-029 OQ-4 Option A).
- 출처: dcy-029 FR-3, OQ-4.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-3로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-046 release-candidate, dcy-029 P1). 근거: 단위/문서 AC 매핑(REQ-086 reason+actor 로그·interface-contract; REQ-088 operator_report 집계·net PnL·KST 경계·CLI report; REQ-089 docs/operations.md 4영역; REQ-090 runtime-flows·project-structure 정합). 14 passed(report+safety_sell), 전체 537 passed/47 skipped 회귀 0, ruff clean. report direct-DB·Loki 실 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -0,0 +1,57 @@
# req-088: 운영 조회 CLI — 보유·오늘 체결·실현 PnL·대기 주문
- Status: Implemented
- Type: Interface
- Priority: High
- Owner: project maintainers
## Intent
- 일일 실현 PnL을 `ledger_outbox`에서 수기 계산해야 했다. 운영자가 단일 CLI 명령으로 현재 보유·오늘 체결·오늘 실현 PnL(수수료·세금 반영)·대기 주문을 조회해 일일 리포트 자동화의 기반을 만든다. (dcy-029 FR-5, OQ-1=CLI, RPC 없음)
## Requirement
- 운영자 CLI(`trex_core/runtime/cli.py`)에 신규 서브커맨드(예: `report` 또는 `pnl`)를 추가해 다음을 출력한다:
- **현재 보유**: holding 슬롯의 symbol/portfolio_id/qty/avg_price.
- **오늘 체결**: 당일(trading_date, KST 경계) 체결 건수/내역.
- **오늘 실현 PnL**: 수수료·세금 반영(BAT-038 정책과 동일 계산), `ledger_outbox`/체결 기록을 단일 권위 출처로 집계.
- **대기 주문**: pending_* 슬롯.
- 조회는 **DB-backed 시점 집계**다. 신규 RabbitMQ RPC는 추가하지 않는다(dcy-029 OQ-1). 데몬 미경유로 DB를 직접 읽거나 기존 read 경로를 재사용한다.
- 청산/체결 항목에 reason+actor(REQ-086)를 함께 보여 안전망/전략 구분이 되게 한다.
- 출력은 사람용 표/요약 + 가능하면 머신 파싱용(예: `--json`) 형태를 고려한다(자동화 기반).
## Acceptance Criteria
1. Given holding 슬롯 존재, When `report` 실행, Then 보유 symbol/qty/avg_price가 출력된다.
2. Given 당일 체결 N건, When 실행, Then 오늘 체결 건수/내역이 출력된다.
3. Given 당일 매도 체결, When 실행, Then 실현 PnL이 수수료·세금 반영 값으로 출력되고 `ledger_outbox` 직접 집계와 일치한다.
4. Given pending_* 슬롯, When 실행, Then 대기 주문이 출력된다.
5. Given "오늘" 경계, When trading_date(KST) 기준, Then 전일 체결은 오늘 집계에서 제외된다.
6. Given 신규 표면, When 실행, Then 신규 RabbitMQ RPC 없이 동작한다(CLI/DB-backed, OQ-1).
## Impacted Area
- Docs: docs/runtime-flows.md(운영자 CLI 조회 흐름), docs/operations.md(사용법 — REQ-089)
- Modules: trex_core/runtime/cli.py(신규 서브커맨드), PnL 집계 read(신규 헬퍼 — `ledger_outbox`/체결 집계), 기존 slot read 재사용
- Tests: 집계 함수 단위(수수료·세금·trading_date 경계), CLI 서브커맨드 단위
## Notes
- PnL 계산은 BAT-038(매도 증권거래세+수수료) 정책을 단일 출처로 재사용(dcy-029 NFR-3/A-3). 부분 정산·재시도 중 outbox 상태는 집계 시점 기준으로 명시.
- 출처: dcy-029 FR-5, OQ-1.
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-5로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-046 release-candidate, dcy-029 P1). 근거: 단위/문서 AC 매핑(REQ-086 reason+actor 로그·interface-contract; REQ-088 operator_report 집계·net PnL·KST 경계·CLI report; REQ-089 docs/operations.md 4영역; REQ-090 runtime-flows·project-structure 정합). 14 passed(report+safety_sell), 전체 537 passed/47 skipped 회귀 0, ruff clean. report direct-DB·Loki 실 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -0,0 +1,54 @@
# req-084: 구조화 로깅 기반 — ISO8601(KST) 타임스탬프 + 레벨 + Loki JSON + correlation id
- Status: Implemented
- Type: Non-Functional
- Priority: High
- Owner: project maintainers
## Intent
- 모든 로그 라인에 시각·레벨이 없어 타임라인 재구성이 불가능했던 문제를 해결한다. ISO8601(KST) 타임스탬프 + 레벨 prefix를 전 로그에 부여하고, Loki 적재용 구조화(JSON) 출력 옵션과 correlation id(intent→order→fill) 전파를 도입해 한 거래의 로그를 단일 키로 묶는다. (dcy-029 FR-1, FR-7)
## Requirement
- 데몬 기동(및 reset CLI)의 로깅 설정을 단일 지점으로 모아, 모든 로그 라인에 **ISO8601 타임스탬프(KST, Asia/Seoul, 환경 TZ 비의존)** + **로그 레벨** prefix를 부여한다.
- 환경 변수(`TREX_LOG_FORMAT`, 기본 `text`)로 출력 포맷을 선택한다: `text`(사람용 한 줄) / `json`(Loki 적재용 구조화 — 최소 `ts`, `level`, `logger`, `msg`, 가능하면 `correlation_id`).
- **correlation id 전파**: contextvar 기반으로 현재 처리의 correlation id를 보관하고, 로깅 필터가 모든 레코드에 주입한다. intent 수락 시 intent_id(또는 그로부터 파생한 키)를 correlation id로 설정해, 같은 거래의 intent·order·fill 로그가 동일 id를 공유한다. id 미설정 시 빈 값/생략으로 안전하게 동작한다.
- 기존 로깅 호출부(`_log.info/...`)는 메시지를 바꾸지 않아도 새 포맷·correlation id가 자동 적용되어야 한다(호출부 광범위 수정 불요).
## Acceptance Criteria
1. Given 로깅 설정 적용 후 임의 로그 1줄, When 출력, Then ISO8601(KST) 타임스탬프 + 레벨 + 메시지를 포함한다.
2. Given `TREX_LOG_FORMAT=json`, When 로그 출력, Then 한 줄이 유효 JSON이며 `ts`/`level`/`logger`/`msg` 키를 포함한다.
3. Given `TREX_LOG_FORMAT` 미설정/`text`, When 로그 출력, Then 사람용 한 줄 포맷(타임스탬프+레벨+메시지)이다.
4. Given correlation id가 설정된 컨텍스트, When 로그 출력, Then 레코드(및 JSON `correlation_id`)에 그 id가 포함된다.
5. Given correlation id 미설정, When 로그 출력, Then 예외 없이 빈/생략 correlation id로 출력된다.
6. Given KST 타임스탬프, When 컨테이너 TZ가 UTC여도, Then 타임스탬프는 KST(+09:00) 기준이다.
## Impacted Area
- Docs: docs/runtime-flows.md(로깅/관측성 흐름 — REQ-090과 공동), docs/project-structure.md(신규 로깅 모듈)
- Modules: 신규 `trex_core/runtime/logging_setup.py`(포맷터+JSON+correlation id 필터·contextvar) 후보, `trex_core/runtime/daemon.py`·`trex_core/runtime/reset.py`(basicConfig 대체), intent 수락 경로(correlation id set)
- Tests: 로그 포맷터 단위(text/json/KST/correlation id), 설정 적용 단위
## Notes
- 기존 `logging.basicConfig(level=INFO)`(daemon.py·reset.py)는 format 미지정으로 타임스탬프·레벨 prefix가 없었다(dcy-029 현재상태).
- correlation id 전파 깊이(전 경로 완전 전파 vs 핵심 경로)는 batch design에서 확정. 최소 intent admission→order dispatch 로깅 연결을 보장한다.
- 출처: dcy-029 FR-1·FR-7, OQ-2(Loki In Scope), A-4(배포 Loki 사용 전제).
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-1·FR-7로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-045 release-candidate, dcy-029 P0). 근거: 단위 AC 매핑(logging_setup text/json/KST/cid/idempotent, execution 주문 결과 submit/fill/reject + cid=slot_id + 거부 ERROR). 35 passed(logging+execution_policy), 전체 529 passed/47 skipped 회귀 0, ruff clean. 실 Loki 적재는 release 운영 검증 위임. Blocking Issues 없음.
@@ -0,0 +1,53 @@
# req-087: 주문 거부 ERROR 가시성 — 조용한 롤백 제거
- Status: Implemented
- Type: Non-Functional
- Priority: High
- Owner: project maintainers
## Intent
- 주문 거부 시 `execution._rollback`이 슬롯을 조용히 전이(`slot_transition_log`에만 기록)해 호가단위 거부(#28)가 로그에 안 보였다. 거부를 **ERROR 레벨 로그**로 즉시 가시화해 반복 거부를 운영자가 즉시 인지하게 한다. (dcy-029 FR-4)
## Requirement
- 주문 거부로 인한 롤백(`pending_buy→inactive` / `pending_sell→holding`) 시 **ERROR 레벨** 로그를 남긴다. 라인은 side, symbol, slot_id, 거부 사유를 포함한다(REQ-085 order_reject 라인과 동일 지점·동일 키, 레벨만 ERROR).
- correlation id(REQ-084)가 있으면 함께 남긴다.
- 알림 전송 채널(claude-bus/외부 webhook 등)은 본 REQ 범위 밖이다(dcy-029 OQ-3 Deferred) — ERROR 로그까지만.
- 정상 체결/정상 전이 경로의 로그 레벨은 바꾸지 않는다(거부 경로만 ERROR).
## Acceptance Criteria
1. Given 매수 주문 거부, When 롤백(pending_buy→inactive), Then ERROR 레벨 로그(side/symbol/slot_id/사유)가 남는다.
2. Given 매도 주문 거부, When 롤백(pending_sell→holding), Then ERROR 레벨 로그가 남는다.
3. Given 정상 체결, When 전이, Then ERROR 로그가 남지 않는다(거부 경로만 ERROR).
4. Given `TREX_LOG_FORMAT=json`, When 거부, Then `level=ERROR` + 사유 키가 구조화 출력된다.
5. Given 반복 거부 N회, When grep `level=ERROR`/`event=order_reject`, Then N건 모두 가시화된다.
6. Given 알림 채널, When 거부, Then 본 반복에서는 전송 채널을 호출하지 않는다(Deferred, 로그까지만).
## Impacted Area
- Docs: docs/runtime-flows.md(주문 집행 거부 가시성)
- Modules: trex_core/application/execution.py(`_rollback`/거부 경로 ERROR 로그), REQ-084·085와 협조
- Tests: tests/application/test_execution* (거부 ERROR caplog 단위, 정상 경로 비-ERROR)
## Notes
- REQ-085(주문 결과 로깅)와 동일한 reject 지점에서 협조 — REQ-085는 일관 키, 본 REQ는 거부 라인의 ERROR 레벨 보장.
- 출처: dcy-029 FR-4, OQ-3(알림 Deferred).
## Change Log
### CHG-20260616-01
- Date: 2026-06-16
- Author: Justin Ko
#### Change Summary
- dcy-029 FR-4로부터 최초 생성(Proposed).
### CHG-20260616-02
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Proposed → **Approved** (confirm-req). 필수 필드·구체 AC 충족, source dcy-029(confirmed, Open OQ 0) 정합. dcy-029 P0/P1 batch 편성 예정.
### CHG-20260616-IMPL
- Date: 2026-06-16
- Author: Justin Ko
- Type: status
- Summary: Approved → **Implemented** (confirm-req-implemented, BAT-045 release-candidate, dcy-029 P0). 근거: 단위 AC 매핑(logging_setup text/json/KST/cid/idempotent, execution 주문 결과 submit/fill/reject + cid=slot_id + 거부 ERROR). 35 passed(logging+execution_policy), 전체 529 passed/47 skipped 회귀 0, ruff clean. 실 Loki 적재는 release 운영 검증 위임. Blocking Issues 없음.
+18 -1
View File
@@ -74,7 +74,7 @@
## Next Requirement ID
- Current: `REQ-083`
- Current: `REQ-091`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -163,9 +163,26 @@
| REQ-080 | trex.slots.strategy_state.set write RPC 계약 — occupancy_seq·version CAS | Interface | Implemented | High | project maintainers | [req-080](./Interface/req-080_strategy-state-set-rpc.md) |
| REQ-081 | 슬롯 occupancy_seq 정합성 가드 + close 시 strategy_state 삭제 불변식 | Data | Implemented | High | project maintainers | [req-081](./Data/req-081_slot-occupancy-seq-guard-and-close-delete.md) |
| REQ-082 | strategy-state baseline 문서 정합 — read/write/삭제 흐름 + occupancy_seq 가드 | Documentation | Implemented | Medium | project maintainers | [req-082](./Documentation/req-082_strategy-state-baseline-alignment.md) |
| REQ-083 | KRX 호가단위(tick) 산출 유틸 — 가격→tick + 배수 내림/올림 | Integration | Implemented | High | project maintainers | [req-083](./Integration/req-083_krx-tick-size-utility.md) |
| REQ-084 | 구조화 로깅 기반 — ISO8601(KST)·레벨·Loki JSON·correlation id | Non-Functional | Implemented | High | project maintainers | [req-084](./Non-Functional/req-084_structured-logging-foundation.md) |
| REQ-085 | 주문 결과 로깅 — submit/체결/거부 일관 tailable 로그 | Integration | Implemented | High | project maintainers | [req-085](./Integration/req-085_order-result-logging.md) |
| REQ-086 | 청산 reason+actor 동반 노출 — 안전망/전략 구분 가시화 | Interface | Implemented | Medium | project maintainers | [req-086](./Interface/req-086_liquidation-reason-actor-exposure.md) |
| REQ-087 | 주문 거부 ERROR 가시성 — 조용한 롤백 제거 | Non-Functional | Implemented | High | project maintainers | [req-087](./Non-Functional/req-087_order-rejection-error-visibility.md) |
| REQ-088 | 운영 조회 CLI — 보유·오늘 체결·실현 PnL·대기 주문 | Interface | Implemented | High | project maintainers | [req-088](./Interface/req-088_operator-pnl-query-cli.md) |
| REQ-089 | 운영자 런북 — docs/operations.md 신설 | Documentation | Implemented | Medium | project maintainers | [req-089](./Documentation/req-089_operator-runbook.md) |
| REQ-090 | 관측성 baseline 문서 정합 — 로깅/관측성·PnL 조회 흐름 | Documentation | Implemented | Medium | project maintainers | [req-090](./Documentation/req-090_observability-baseline-alignment.md) |
## Recent Change Log Summary
- 2026-06-16 :: REQ-086·088·089·090 Approved → **Implemented** (confirm-req-implemented, BAT-046 release-candidate, dcy-029 P1/issue #29): 청산 reason+actor 노출 + 운영 조회 CLI(report, 보유·오늘 체결·실현 PnL net·대기) + 운영자 런북 docs/operations.md + baseline 정합. 14 passed(신규 operator_report+safety_sell), 전체 537 passed/47 skipped 회귀 0, ruff clean.
- 2026-06-16 :: REQ-084·085·087 Approved → **Implemented** (confirm-req-implemented, BAT-045 release-candidate, dcy-029 P0/issue #29): 구조화 로깅 기반(ISO8601 KST·레벨·Loki JSON·correlation id) + 주문 결과 로깅(event=order_submit|fill|reject) + 거부 ERROR 가시화 구현·검증. 35 passed(신규 logging+주문결과), 전체 529 passed/47 skipped 회귀 0, ruff clean.
- 2026-06-16 :: REQ-084~090 신규 생성(Proposed, draft-req dcy-029): 운영 관측성 — REQ-084 구조화 로깅 기반(ISO8601 KST·레벨·Loki JSON·correlation id, FR-1+7), REQ-085 주문 결과 로깅(FR-2), REQ-086 청산 reason+actor 노출(FR-3, OQ-4 Option A), REQ-087 거부 ERROR 가시성(FR-4), REQ-088 운영 조회 CLI(FR-5, OQ-1 CLI), REQ-089 운영자 런북 docs/operations.md(FR-8), REQ-090 baseline 정합(FR-6). P0=084·085·087(+087은 P1이나 로깅 동반)/ P1=086·088·089·090.
- 2026-06-16 :: REQ-083·070 Approved → **Implemented** (confirm-req-implemented, BAT-044 release-candidate, dcy-030/issue #28): 슬리피지 KRX 호가단위 스냅 구현·검증 완료 — `domain/pricing.py`(tick 유틸) + `execution.py` 스냅(상한 준수 매수 floor/매도 ceil + band<tick 보장 + epsilon 가드). issue #28 케이스(147700→148400/54500→54700) 단위 검증, 47 passed(신규 pricing+슬리피지 정정), 전체 516 passed/47 skipped 회귀 0, ruff clean.
- 2026-06-16 :: REQ-083 Proposed → **Approved** (confirm-req): 필수 필드·구체 AC 충족, source dcy-030(confirmed, Open OQ 0) 정합. REQ-070(Approved, CHG)와 함께 dcy-030 단일 batch 편성 예정.
- 2026-06-16 :: REQ-083 신규 생성(Proposed, draft-req dcy-030): KRX 호가단위(tick) 산출 유틸 — 가격→tick 순수 함수(2023.1.25~ 구간표) + floor/ceil 배수 헬퍼. 주식 전용(OQ-1). REQ-070 슬리피지 스냅이 소비.
- 2026-06-16 :: REQ-070 change-req (CHG-20260616-01, dcy-030/issue #28): 슬리피지 실효 지정가에 KRX 호가단위 스냅 추가 + 반올림 방향 전환(체결 보장 → **상한 준수**: 매수 내림/매도 올림) + band<1tick 하한/상한 보장. 기존 int(ceil/floor) 무스냅 구현 무효화 → Implemented → **Approved** 되돌림. 신규 AC-7~10, AC-1·2 갱신. dcy-030 batch에서 재구현·검증.
- 2026-06-15 :: REQ-007 Approved → **Implemented** (confirm-req-implemented, BAT-043 release-candidate, issue #27): rejected SellIntent 응답 additive `retryable` 구현·검증 완료 — core 소유 `_SELL_REJECT_RETRYABLE` 매핑 + helper, 487 passed(+8), ruff clean. issue #27 close.
- 2026-06-15 :: REQ-007 change-req (CHG-20260615-01, issue #27): rejected SellIntent 응답에 additive `retryable: bool`(core 소유 reason→retryable 매핑, 미인식 기본 true). #26 sell-idempotency 후속 — 데몬 손절매 재시도 안전 경로 decoupling. 완전 additive(기존 불변) → 신규 AC-7 구현·검증 대기 → Implemented → **Approved** 되돌림.
- 2026-06-15 :: REQ-079·080·081·082·073·074 Approved → **Implemented** (confirm-req-implemented, BAT-042 release-candidate, dcy-028): slot strategy-state 저장소 구현·검증 완료 — `slot_strategy_state` 테이블+StrategyStateStore(in-memory+PG)+occupancy_seq·version CAS(REQ-079), write RPC `trex.slots.strategy_state.set`(REQ-080), occupancy_seq 가드+close 삭제(REQ-081), baseline 정합(REQ-082), slots.req 행 strategy_state·occupancy_seq additive(REQ-073 AC-7/REQ-074 AC-6). 479 passed (+33 신규: store CAS 6+ABA, occupancy bump/close 4경로, set RPC 9, slots read 5), ruff clean. PG 경로 게이트 테스트 작성(실 DB 검증 release 위임). Blocking Issues 없음.