Add dcy-003 (confirmed) + REQ-011~015: broker execution + KIS + outbox

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>
This commit is contained in:
2026-06-04 16:40:23 +09:00
co-authored by Claude Opus 4.8
parent 575ba9f513
commit d60d720bc7
8 changed files with 593 additions and 2 deletions
@@ -0,0 +1,69 @@
# req-015: 브로커/집행 baseline 문서 정합
- Status: Proposed
- Type: Documentation
- Priority: Medium
- Owner: project maintainers
## Intent
- 브로커 세션·주문 집행·체결·reconciliation 레이어가 추가된 뒤 baseline 문서를 실제 구조/흐름/계약과 일치시킨다.
## Requirement
- `docs/runtime-flows.md`(집행 루프·체결·reconciliation 흐름), `docs/project-structure.md`(broker adapter·execution 레이어), `docs/interface-contract.md`(BrokerPort 경계·KIS), `docs/data-model.md`(broker_order_id 를 실행큐/멱등 가드로 쓰는 의미)를 갱신한다.
## Acceptance Criteria
1. Given 집행 구현 완료, When runtime-flows 확인, Then 집행 루프(claim→송신→poll→전이)·reconciliation 흐름이 실제와 일치한다.
2. Given project-structure 확인, Then broker adapter(paper/KIS)·execution 레이어가 반영된다.
3. Given interface-contract/data-model 확인, Then BrokerPort 경계와 broker_order_id 의 실행큐/멱등 역할이 반영된다.
## Impacted Area
- Docs: docs/runtime-flows.md, docs/project-structure.md, docs/interface-contract.md, docs/data-model.md
- Modules: 없음
- Tests: 없음
## Notes
- dcy-003 FR-6. REQ-011~014 구현 완료 후 수행(순서 의존).
- 출처: dcy-003 FR-6.
## Change Log
### CHG-20260604-01
- Date: 2026-06-04
- Author: Justin Ko
#### Change Summary
- dcy-003 FR-6 로부터 최초 생성(Proposed).
#### Intent
- 브로커/집행 baseline 정합 요구사항을 backlog 로 정규화.
#### Acceptance Criteria Delta
- Added:
- runtime-flows, project-structure, interface-contract/data-model 정합 3개 기준
- Updated:
- 없음
- Removed:
- 없음
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md, docs/project-structure.md, docs/interface-contract.md, docs/data-model.md
- Modules:
- 없음
- Tests:
- 없음
#### Delivery Trace Delta
- Batches:
- none
- Releases:
- none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: REQ-011~014 구현 후 batch verification 단계에서 수행
#### Validation Plan
- baseline 문서와 실제 구현(레이어/흐름/계약) 대조로 검증.
@@ -0,0 +1,70 @@
# req-014: 주문 핸드오프 durability + reconciliation
- Status: Proposed
- Type: Exception
- Priority: High
- Owner: project maintainers
## Intent
- 집행 도중 크래시가 나도 중복 주문 없이 일관 상태로 복구되도록, 옵션 A(pending 슬롯=실행큐 + broker_order_id 멱등)에 재기동 reconciliation 을 더한다.
## Requirement
- 재기동 시 코어가 `broker_order_id` 가 채워진 pending 슬롯을 브로커 주문 상태와 대조해 reconciliation 한다: 체결됨→해당 전이(holding/closed), 거부/취소됨→롤백(idle), 미체결→계속 poll. `broker_order_id` 가 비어 있는 pending 슬롯은 미송신으로 보고 정상 claim 경로로 재개한다. 동일 슬롯/주문에 대해 중복 주문이 발생하지 않는다.
## Acceptance Criteria
1. Given 주문 송신 후 broker_order_id 기록까지 된 상태에서 크래시, When 재기동 reconciliation, Then 같은 슬롯에 재주문하지 않고 브로커 상태로 전이를 정리한다(중복 주문 0).
2. Given 주문 송신 전(broker_order_id NULL) 크래시, When 재기동, Then 정상 claim 으로 재개해 1회만 송신한다.
3. Given 브로커에서 이미 체결된 주문, When reconciliation, Then 슬롯이 holding/closed 로 수렴한다.
4. Given 동일 집행이 두 번 수행(루프 중복 틱), When 점검, Then broker_order_id 멱등 가드로 중복 주문이 생기지 않는다. (NFR-3)
## Impacted Area
- Docs: docs/runtime-flows.md(reconciliation 흐름) — REQ-015
- Modules: trex_core 집행/복구 컴포넌트(REQ-013 루프에 reconcile 단계), 브로커 주문 상태 조회 재사용
- Tests: 크래시 주입(송신 전/후) 후 reconciliation, 중복 주문 0, 멱등 재틱
## Notes
- 옵션 A 기반(별도 outbox 테이블 없음). 부분체결/재시도 본격화 시 옵션 B 승격은 후속.
- 출처: dcy-003 FR-5, NFR-3. 핵심 안전(R-1) 완화의 실현.
## Change Log
### CHG-20260604-01
- Date: 2026-06-04
- Author: Justin Ko
#### Change Summary
- dcy-003 FR-5 로부터 최초 생성(Proposed). NFR-3 흡수.
#### Intent
- durable 핸드오프 + reconciliation(크래시 복구·멱등) 요구사항을 backlog 로 정규화.
#### Acceptance Criteria Delta
- Added:
- 송신후 크래시 reconciliation, 송신전 크래시 재개, 체결 수렴, 멱등 재틱 4개 기준
- Updated:
- 없음
- Removed:
- 없음
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md
- Modules:
- 집행/복구 컴포넌트(reconcile)
- Tests:
- 크래시 주입 reconciliation 테스트
#### Delivery Trace Delta
- Batches:
- none
- Releases:
- none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 편성
#### Validation Plan
- 크래시 주입(송신 전/후) reconciliation + 중복 주문 0 테스트로 검증.
@@ -0,0 +1,69 @@
# req-011: BrokerPort 추상화 + paper/stub async 더블
- Status: Proposed
- Type: Integration
- Priority: High
- Owner: project maintainers
## Intent
- 브로커를 코어에서 추상화하는 `BrokerPort` 를 정의하고(불변식 B 의 단일 경계), 결정적 검증용 paper/stub 어댑터를 제공한다. 이후 KIS 어댑터(REQ-012)와 집행 루프(REQ-013)가 이 포트 위에서 동작한다.
## Requirement
- `BrokerPort`(application 포트)에 `submit_order(side, symbol, qty, ...) -> broker_order_id`, `cancel_order(broker_order_id)`, `poll_fill(broker_order_id) -> FillStatus(accepted/partially_filled/filled/rejected/cancelled, avg_price, filled_qty)` 를 정의한다. paper/stub 어댑터는 동기 단축 없이 submit→poll 비동기 계약을 따르되 체결 시점·부분체결·거부를 프로그래밍 가능한 결정적 더블로 제공한다. 어댑터는 adapters 레이어에 두고 도메인은 의존하지 않는다.
## Acceptance Criteria
1. Given `BrokerPort` 정의, When paper 어댑터로 `submit_order`, Then `accepted` + broker_order_id 를 반환하고 즉시 `filled` 로 단축하지 않는다(다음 `poll_fill` 에서 체결).
2. Given paper 더블의 fill 시나리오 설정(즉시/N틱 후/부분/거부), When `poll_fill` 반복, Then 설정대로 결정적으로 상태가 진행된다.
3. Given 코드, When import 스윕, Then `trex_core.domain.slot` 은 broker/네트워크 의존이 0이고 BrokerPort 구현은 adapters 레이어에만 있다. (NFR-1/NFR-2)
## Impacted Area
- Docs: docs/interface-contract.md(브로커 경계) — REQ-015 에서 정합
- Modules: trex_core/application(BrokerPort), trex_core/adapters/broker(paper/stub)
- Tests: paper 더블 fill 시나리오 테스트
## Notes
- 불변식 B 의 단일 경계. KIS 어댑터는 REQ-012, 집행 루프는 REQ-013.
- 출처: dcy-003 FR-1(포트+paper), NFR-1/NFR-2 흡수.
## Change Log
### CHG-20260604-01
- Date: 2026-06-04
- Author: Justin Ko
#### Change Summary
- dcy-003 FR-1(포트+paper) 로부터 최초 생성(Proposed).
#### Intent
- BrokerPort + paper async 더블 요구사항을 backlog 로 정규화.
#### Acceptance Criteria Delta
- Added:
- submit→poll 비동기 계약, 결정적 fill 시나리오, 도메인 순수성 3개 기준
- Updated:
- 없음
- Removed:
- 없음
#### Impacted Area Delta
- Docs:
- docs/interface-contract.md
- Modules:
- application(BrokerPort), adapters/broker(paper)
- Tests:
- paper 더블 시나리오 테스트
#### Delivery Trace Delta
- Batches:
- none
- Releases:
- none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 편성
#### Validation Plan
- paper 더블 비동기 체결 시나리오 단위테스트로 검증.
@@ -0,0 +1,72 @@
# req-012: KIS Open API 브로커 어댑터
- Status: Proposed
- Type: Integration
- Priority: High
- Owner: project maintainers
## Intent
- `BrokerPort`(REQ-011)를 구현하는 실제 KIS(한국투자증권) Open API 어댑터를 추가해, 코어가 실제 주문 송신/취소/체결 조회를 수행할 수 있게 한다. 슬라이스에서는 KIS 모의투자 서버로 검증한다.
## Requirement
- KIS Open API 로 `submit_order`/`cancel_order`/`poll_fill`(체결 조회)을 구현하고, 접속 토큰 발급·갱신, 레이트리밋, 모의투자/실계좌 base URL 전환을 어댑터 내부에서 처리한다. 자격증명은 env/.env(REQ-010 패턴)로 주입한다. 실계좌 라이브 전환은 config 게이팅(기본 모의투자)으로 둔다.
## Acceptance Criteria
1. Given KIS 모의투자 자격증명, When 어댑터 기동, Then 토큰을 발급/갱신하고 인증된 호출이 가능하다.
2. Given 매수/매도 주문, When `submit_order`, Then KIS 모의투자에 주문이 접수되고 broker_order_id(주문번호)를 반환한다.
3. Given 접수된 주문, When `poll_fill`, Then KIS 체결 조회로 체결/부분체결/거부 상태를 반환한다.
4. Given config, When 실계좌/모의투자 전환, Then 기본은 모의투자이며 실계좌는 명시적 게이팅 없이는 활성화되지 않는다.
5. Given 자격증명 미설정/토큰 실패, When 호출, Then 명확한 오류로 실패하고 코어 슬롯 상태를 오염시키지 않는다.
## Impacted Area
- Docs: docs/interface-contract.md(브로커 경계/KIS), docs/runtime-flows.md — REQ-015
- Modules: trex_core/adapters/broker(kis), config(KIS 자격증명/base URL/게이팅), pyproject(HTTP 의존)
- Tests: KIS 모의투자 통합테스트(자격증명 가용 시), 토큰/오류 처리 단위테스트
## Notes
- 실거래 리스크(dcy-003 R-5): 슬라이스는 모의투자만, 실계좌 라이브는 Out of Scope(게이팅).
- KIS 모의투자 자격증명이 검증 환경에 없으면 통합테스트는 skip, 단위(토큰/오류)만 수행 — verification 에서 분리 판단.
- 출처: dcy-003 FR-1(KIS), OQ-1.
## Change Log
### CHG-20260604-01
- Date: 2026-06-04
- Author: Justin Ko
#### Change Summary
- dcy-003 FR-1(KIS 어댑터) 로부터 최초 생성(Proposed).
#### Intent
- 실제 KIS Open API 어댑터 요구사항을 backlog 로 정규화.
#### Acceptance Criteria Delta
- Added:
- 토큰, 주문 접수, 체결 조회, 모의투자/실계좌 게이팅, 오류 처리 5개 기준
- Updated:
- 없음
- Removed:
- 없음
#### Impacted Area Delta
- Docs:
- docs/interface-contract.md, docs/runtime-flows.md
- Modules:
- adapters/broker(kis), config, pyproject
- Tests:
- KIS 모의투자 통합 + 토큰/오류 단위
#### Delivery Trace Delta
- Batches:
- none
- Releases:
- none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 편성
#### Validation Plan
- KIS 모의투자 통합테스트(가용 시) + 토큰/오류 단위테스트로 검증.
@@ -0,0 +1,72 @@
# req-013: 주문 집행 루프 (claim·송신·체결·롤백)
- Status: Proposed
- Type: Integration
- Priority: High
- Owner: project maintainers
## Intent
- 코어 데몬 내 백그라운드 execution 루프가 pending 슬롯을 집행해 브로커에 주문을 송신하고 체결을 슬롯 상태로 반영한다(불변식 A 단일 writer 유지). intent API 는 pending 전이까지만, 집행은 루프가 비동기 수행.
## Requirement
- 데몬 프로세스 내 별도 execution 루프가 주기적으로: ① `pending_buy`/`pending_sell` 슬롯을 `FOR UPDATE SKIP LOCKED`(broker_order_id IS NULL)로 claim → `BrokerPort.submit_order` → `broker_order_id` 기록(옵션 A), ② broker_order_id 있는 pending 슬롯을 `poll_fill` 로 비동기 관측해 매수 체결 시 `pending_buy→holding`(avg_price/qty), 매도 체결 시 `pending_sell→closed`(recovery 재진입 +1), ③ 거부/취소 시 `pending_buy→idle` 롤백을 수행한다. 모든 슬롯 쓰기는 SlotService(advisory lock) 단일 경로.
## Acceptance Criteria
1. Given pending_buy 슬롯(paper), When 집행 루프 1회, Then 매수 주문 송신 + broker_order_id 기록, broker_order_id 채워진 슬롯은 재디스패치되지 않는다(멱등). (NFR-2 단일 writer)
2. Given 송신된 매수 주문이 체결(poll), When 루프, Then `pending_buy→holding`(avg_price/qty 반영).
3. Given 매수 주문 거부(poll), When 루프, Then `pending_buy→idle` 롤백.
4. Given pending_sell 슬롯, When 집행+체결, Then 매도 주문 송신 → `pending_sell→closed` + 재진입 +1.
5. Given 슬롯 쓰기 경로, When 점검, Then 집행 루프도 SlotService(advisory lock)로만 슬롯을 전이한다(브로커 직접 슬롯 쓰기 없음).
## Impacted Area
- Docs: docs/runtime-flows.md(집행/체결 흐름) — REQ-015
- Modules: trex_core/application 또는 runtime(execution 루프), SlotService 재사용
- Tests: paper 더블로 매수/매도 lifecycle, 멱등 재디스패치, 거부 롤백, 체결→전이
## Notes
- OQ-3(옵션 A 실행큐)·OQ-4(별도 루프)·OQ-2(비동기 poll) 결정 반영. 폴링 주기/배치 크기는 config.
- reconciliation·크래시 복구는 REQ-014. KIS 어댑터는 REQ-012, paper 는 REQ-011.
- 출처: dcy-003 FR-2, FR-3, FR-4. NFR-2 흡수.
## Change Log
### CHG-20260604-01
- Date: 2026-06-04
- Author: Justin Ko
#### Change Summary
- dcy-003 FR-2·FR-3·FR-4 로부터 최초 생성(Proposed). NFR-2 흡수.
#### Intent
- 주문 집행 루프(매수/매도 claim·송신·체결·롤백) 요구사항을 backlog 로 정규화.
#### Acceptance Criteria Delta
- Added:
- 매수 claim/멱등, 매수 체결→holding, 거부 롤백, 매도 체결→closed, 단일 writer 5개 기준
- Updated:
- 없음
- Removed:
- 없음
#### Impacted Area Delta
- Docs:
- docs/runtime-flows.md
- Modules:
- application/runtime(execution 루프)
- Tests:
- paper lifecycle/멱등/롤백/체결 테스트
#### Delivery Trace Delta
- Batches:
- none
- Releases:
- none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 batch 편성
#### Validation Plan
- paper 더블 매수/매도 lifecycle + 멱등 + 롤백 테스트로 검증.
+7 -1
View File
@@ -74,7 +74,7 @@
## Next Requirement ID
- Current: `REQ-011`
- Current: `REQ-016`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -91,9 +91,15 @@
| REQ-008 | 슬롯 read-only 조회 HTTP API | Interface | Implemented | High | project maintainers | [req-008](./Interface/req-008_slot-readonly-query-api.md) |
| REQ-009 | 데몬/API/영속화 baseline 문서 정합 | Documentation | Implemented | Medium | project maintainers | [req-009](./Documentation/req-009_daemon-api-baseline-alignment.md) |
| REQ-010 | 데몬 설정 .env 파일 로딩 | Configuration | Implemented | Medium | project maintainers | [req-010](./Configuration/req-010_daemon-dotenv-loading.md) |
| REQ-011 | BrokerPort 추상화 + paper/stub async 더블 | Integration | Proposed | High | project maintainers | [req-011](./Integration/req-011_broker-port-and-paper-double.md) |
| REQ-012 | KIS Open API 브로커 어댑터 | Integration | Proposed | High | project maintainers | [req-012](./Integration/req-012_kis-broker-adapter.md) |
| REQ-013 | 주문 집행 루프 (claim·송신·체결·롤백) | Integration | Proposed | High | project maintainers | [req-013](./Integration/req-013_order-execution-loop.md) |
| REQ-014 | 주문 핸드오프 durability + reconciliation | Exception | Proposed | High | project maintainers | [req-014](./Exception/req-014_order-handoff-durability-reconciliation.md) |
| REQ-015 | 브로커/집행 baseline 문서 정합 | Documentation | Proposed | Medium | project maintainers | [req-015](./Documentation/req-015_broker-execution-baseline-alignment.md) |
## Recent Change Log Summary
- 2026-06-04 :: REQ-011~015 최초 생성(Proposed) — dcy-003 FR-1~FR-6 분해. (draft-req)
- 2026-06-04 :: REQ-010 Approved → Implemented — BAT-003 verification evidence 기반. (confirm-req-implemented)
- 2026-06-04 :: REQ-010 생성 + Approved — 데몬 .env 로딩 (minor-change). (draft-req/confirm-req)
- 2026-06-03 :: REQ-005~009 Approved → Implemented — BAT-002 verification evidence 기반. (confirm-req-implemented)