Files
trex-core/docs/discovery/dcy-013_20260608_kis-external-cancel-pending-sell-stuck.md
T
genichinandClaude Opus 4.8 4746f74aae fix(broker): dcy-013 KIS 외부 취소 감지 + 부분 체결 회계 + stale 워치독 (BAT-017)
KIS 계좌에서 직접 매도 주문을 취소하면 poll_fill 이 cncl_yn 을 파싱하지 않아
슬롯이 pending_sell 에 영구히 갇히고 죽은 주문을 무한 폴링하던 버그(issue #9)
정정.

거버넌스: 전부 change-req (신규 REQ 없음, dcy-013 OQ-3).
- REQ-012: KIS poll_fill cncl_yn 파싱 → 외부 취소 감지. FillStatus.cancelled
  /is_partial_cancel 추가. 체결 0 취소→cancelled, 부분 체결 후 취소→partial+cancelled
- REQ-013: 집행 _on_partial_cancel — 체결분 원장 1회 + qty 차감(매도 잔여/매수 체결분)
  + holding 복귀 (OQ-1 A안). 전량 취소는 기존 롤백 경로 재사용
- REQ-018: 부분 체결분 원장 1회 기록 (_record_ledger 재사용)
- REQ-031: 잔여 포지션 정합 연계 (slot.qty ↔ 실 잔고, 과매도 방지)
- REQ-014: pending stale 워치독 Alert-only (TREX_PENDING_STALE_THRESHOLD,
  WARN+카운터, 상태 미변경) — 취소 감지 누락 backstop
- REQ-015: interface-contract/runtime-flows 정합

전량 취소는 holding 자동 복구(limit_price clear→재매도 시장가, dcy-012 연계).
KIS cncl_yn 실 규약은 운영 검증(미지 값 보수 처리 + 워치독 backstop).

검증: 단위 294 passed/32 skipped, 인프라 게이트(PG+RabbitMQ) 326 passed, ruff clean.
신규 test_kis_cancel(httpx stub) + test_execution_cancel(programmable broker).
BAT-017 release-candidate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:11:49 +09:00

23 KiB

0. 문서 상태

이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.

  • 상태: confirmed
  • 문서 ID: dcy-013_20260608_kis-external-cancel-pending-sell-stuck
  • 이슈명: KIS 외부 주문 취소 시 슬롯이 pending_sell 에 영구히 갇힘 — cncl_yn 미파싱
  • 작성 시각(KST): 2026-06-08 13:29 KST
  • 마지막 갱신 시각(KST): 2026-06-08 16:30 KST
  • 대체됨: 없음
  • 후속 Discovery 참조: 없음
  • 생성된 REQ 참조: REQ-012/013/018/031/014/015 (전부 change-req, 신규 REQ 없음 — OQ-3). REQ-013/018/015=CHG-20260608-02, REQ-012/031/014=CHG-20260608-01. 워치독 임계 env 는 REQ-014 에 흡수. delivery: BAT-017

1. 계획 상태 요약

현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.

  • 연계 문서 현황:
    • 관련 점수 파일: 미생성
    • 관련 TODO/메모: GitHub issue #9 (fourblocks2020/trex-core), 관련 issue #10(dcy-012, 매도 가격 버그)
  • 해석:
    • 실제 KIS poll_fill 이 일별주문체결조회의 취소여부(cncl_yn)를 파싱하지 않아, 계좌에서 직접(trex-core 외부) 매도 주문을 취소하면 슬롯이 pending_sell 에 영구히 갇히고 데몬이 죽은 주문을 매 tick 무한 폴링하는 버그를 정식 SDLC 주기로 착수한다.
    • 이번 Discovery에서는 KIS 어댑터의 취소 감지 갭을 메우는 핵심 수정과, pending 주문의 stale 처리(워치독/타임아웃) 보강 범위를 판정한다. 이미 Implemented·released(REL-001/003) 된 집행/브로커 경로(dcy-003) 변경이므로, 거버넌스는 OQ-3 결정에 따라 기존 REQ(REQ-012/013/018/031/014/015) change-req 로 처리하고 신규 REQ 는 원칙적으로 생성하지 않는다(워치독 임계 env 는 조건부).

2. 요구사항 판정 결과

이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.

  • 판정: 신규
  • 근거
    • 기존 Discovery(dcy-001~dcy-012) 중 KIS 외부 취소 감지(cncl_yn 파싱)나 pending 주문 stale 워치독을 다룬 문서는 없다. dcy-003(broker execution+outbox)은 집행 루프·롤백 경로를 도입했고, dcy-012(issue #10)는 매도 가격 버그를 다뤘으나 poll_fill 의 취소 감지 갭은 명시적으로 범위 밖(후속 이슈)으로 분리했다.
    • 변경이 이미 Implemented·released 된 KIS 어댑터(poll_fill)와 집행 reconciliation 의미를 바꾸므로, 기존 Discovery 미세 조정이 아니라 독립 주기로 추적하는 것이 명확하다.

3. 문제점의 요약

문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.

  • 현재 상태
    • 취소를 종료 상태로 다루는 설계는 이미 존재한다 — trex_core/application/broker_port.py 의 FillStatus.is_terminal_reject(broker_port.py:6364)는 rejected·cancelled 를 모두 포함하고, _poll(execution.py:113)은 is_terminal_reject 면 _rollback(execution.py:198~)을 호출해 PENDING_SELL → HOLDING 으로 되돌리고 clear_dispatch 로 broker_order_id 를 비운다(execution.py:207~210).
    • 그러나 실제 KIS poll_fill(trex_core/adapters/broker/kis.py:163~208)은 취소여부(cncl_yn)를 파싱하지 않는다. 계좌에서 직접 취소하면 일별주문체결조회(inquire-daily-ccld)에 주문 row 는 남지만 체결수량(tot_ccld_qty)이 0이므로, if ccld_qty <= 0: return FillStatus(state="accepted", ...)(kis.py:191~192)로 빠져 accepted(접수됨) 로 판정된다. _poll 은 accepted 를 "다음 tick 대기"로 처리해 슬롯이 영구히 pending_sell 에 머문다.
    • 부분 체결 후 취소(0 < ccld_qty < ord_qty)도 같은 문제다 — partially_filled(kis.py:207~)로 판정되어 역시 "다음 tick 대기"로 처리되어 갇힌다.
    • paper 브로커는 취소를 올바르게 처리한다 — trex_core/adapters/broker/paper.py:74~75 에서 o.cancelled 면 FillStatus(state="cancelled") 를 반환한다. 즉 갭은 실제 KIS 어댑터에만 존재한다.
    • baseline 문서(docs/project-structure.md, docs/runtime-flows.md)는 존재하며 최신이다. 집행 폴/롤백은 기존 runtime flow 에 포함돼 있고, 이번 변경은 KIS 어댑터의 취소 감지 단계를 메운다.
  • 기대 상태
    • KIS poll_fill 이 외부 취소를 FillStatus(state="cancelled") 로 매핑하면, 기존 롤백 경로가 동작해 슬롯이 HOLDING 으로 복귀하고 broker_order_id 가 비워져 자동 회복된다. (dcy-012 구현 가정 — HOLDING 진입 시 limit_price 가 clear 되어 재매도는 시장가로 나가 체결성이 보장된다.)
    • 죽은 주문에 대한 무한 1초 폴링이 멈추고, 운영자 수동 개입 없이 자동 복구된다. 보강책으로 pending 주문이 비정상적으로 오래 머무는 경우 stale 처리(워치독/타임아웃)가 안전망이 된다.
  • 이해관계자
    • 문서 작성자(AI agent) — Discovery/REQ/Batch 산출물 작성
    • 리뷰어/승인자 — KIS 어댑터·reconciliation 변경 승인
    • 운영 담당자 — 외부 취소·갇힘 상황의 자동 복구로 수동 개입 부담 감소
    • 전략 모듈 — 슬롯이 자동 복구되어 일관된 상태를 관측
  • 제약사항
    • 이미 released(REL-001/003) 된 KIS 어댑터/집행 경로 변경이므로 ad-hoc 수정이 아니라 정식 SDLC(change-req 또는 신규 REQ) 경유가 필요하다.
    • KIS inquire-daily-ccld 응답의 실제 cncl_yn(또는 동등) 필드명·값 규약을 실데이터로 확인해야 정확히 매핑할 수 있다.
    • 부분 체결 후 취소는 체결분 원장 귀속과 잔여 포지션 정합을 함께 고려해야 한다(단순 롤백으로 과매도 위험).

주요 사용자 시나리오

사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.

  • 운영자가 KIS HTS/MTS 에서 trex-core 가 낸 매도 주문을 직접 취소한다 → core 가 다음 tick 에 취소를 감지해 슬롯을 HOLDING 으로 복귀시키고, 필요 시 재매도(시장가)한다.
  • 부분 체결 후 운영자가 잔량을 취소한다 → 체결분은 원장에 기록되고 잔여 포지션만 정합 처리되어 과매도가 발생하지 않는다.
  • 어떤 이유로 pending 주문이 비정상적으로 오래 머문다 → 워치독/타임아웃이 stale 로 감지해 reconciliation 또는 경고를 발생시킨다.

4. 이번에 정의할 변경

이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.

  • KIS poll_fill 이 inquire-daily-ccld 응답의 취소여부(cncl_yn 등)를 파싱해, 취소된 주문(체결 0 또는 부분 체결 후 취소)을 FillStatus(state="cancelled") 로 매핑한다 — 기존 is_terminal_reject → _rollback 경로가 동작하도록.
  • 부분 체결 후 취소(OQ-1 A안): 체결분 원장 기록 + 슬롯 qty 차감 + 잔여 HOLDING 복귀의 부분 체결 회계를 도입한다(과매도/원장 누락 방지).
  • (OQ-2 — Alert-only) pending 주문 stale 워치독을 도입한다 — 임계 초과 시 WARN/메트릭 가시화만, 상태 미변경(auto-remediation 은 후속).
  • 인터페이스/런타임 baseline 문서에 취소 감지·복구 흐름을 반영한다.

영향 범위

변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.

  • 코드 영향:
    • trex_core/adapters/broker/kis.py — poll_fill(163~208) 에 cncl_yn 파싱 + state="cancelled" 매핑(핵심 갭)
    • trex_core/application/broker_port.py — FillStatus 계약(필요 시 부분 체결+취소 표현 보강)
    • trex_core/application/execution.py — 완전 취소(체결 0)는 기존 _poll/_rollback 경로 자동 재사용. 부분 체결+취소(OQ-1 A안)는 체결분 원장 기록 + 슬롯 qty 차감 + 잔여 HOLDING 복귀의 부분 체결 회계 경로 신규(_on_filled/_record_ledger 가 전량 체결만 다루던 것을 부분에도 확장)
    • trex_core/domain/slot/ — 슬롯 qty 부분 차감 후 HOLDING 복귀 전이(잔여 수량 갱신)
    • (워치독 채택 시) pending stale 감지 컴포넌트 — 집행 reconciliation 경로
  • 문서 영향:
    • docs/interface-contract.md — KIS poll/fill 상태 매핑(취소 포함) 반영
    • docs/runtime-flows.md — 외부 취소 감지 → 롤백 → 재매도/회복 흐름 반영
  • 운영 영향:
    • 외부 취소·갇힘의 자동 복구로 수동 개입·불필요 폴링 감소
    • (워치독) stale 임계·알람 운영 파라미터 추가 가능

5. 요구사항 목록

실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.

기능 요구사항

  • FR-1: KIS poll_fill 은 inquire-daily-ccld 응답의 취소여부를 파싱해, 외부 취소된 주문(체결 0)을 FillStatus(state="cancelled") 로 매핑한다. 이로써 기존 is_terminal_reject → _rollback 경로가 동작해 슬롯이 HOLDING 으로 자동 복귀한다.
  • FR-2: 부분 체결 후 취소(0 < ccld_qty < ord_qty)를 감지해 (OQ-1 A안) ① 체결분(ccld_qty)을 원장에 1회 기록, ② 슬롯 qty 를 ccld_qty 만큼 차감, ③ 잔여 qty 로 HOLDING 복귀해 잔여분만 재매도 가능하게 한다. avg_price 는 유지하여 잔여 포지션 정합을 보장하고 과매도/원장 누락을 방지한다.
  • FR-3: (OQ-2 — Alert-only) pending 주문이 configurable 임계 시간을 초과해 머물면 stale 로 감지해 WARN 로그·메트릭으로 가시화한다. 슬롯/주문 상태는 변경하지 않는다(자동 롤백/취소는 후속). cncl_yn 매핑 오류(R-1) 등 미지 원인의 무한 갇힘을 silent 가 아니라 운영자에게 노출하는 안전망이다.
  • FR-4: docs/interface-contract.md 와 docs/runtime-flows.md 에 취소 감지·복구(및 워치독) 흐름을 반영한다.

비기능 요구사항

성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.

  • NFR-1: 자동 회복성 — 외부 취소된 슬롯이 운영자 개입 없이 다음 tick 내에 HOLDING 으로 복구되어 pending_sell 영구 갇힘이 발생하지 않아야 한다.
  • NFR-2: 자원 효율 — 죽은(취소된) 주문에 대한 무한 폴링이 중단되어 불필요한 KIS API 호출이 발생하지 않아야 한다.
  • NFR-3: 정합성 — 부분 체결 후 취소에서 체결분이 원장에 정확히 귀속되고 잔여 포지션이 실제 잔고와 일치해야 한다(과매도/이중매도 금지).

범위 경계

이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.

  • In Scope
    • KIS poll_fill 의 cncl_yn 파싱 + cancelled 매핑(핵심 갭)
    • 부분 체결 후 취소 처리(OQ-1 A안: 체결분 원장 기록 + qty 차감 + 잔여 HOLDING 복귀)
    • pending stale 워치독(OQ-2 Alert-only: WARN/메트릭 가시화)
    • 인터페이스/런타임 문서 갱신
  • Out of Scope
    • buy 경로·paper 브로커 동작 변경(paper 는 이미 정상)
    • 매도 가격 정책(dcy-012 에서 처리 — 본 주기는 취소 감지만)
    • 워치독 auto-remediation(타임아웃 시 자동 롤백/취소) — 정상 slow fill·지정가 대기 상호작용·KIS 취소 능력 필요로 후속 분리

6. 리스크/가정 목록

불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.

리스크

  • R-1 (High): KIS inquire-daily-ccld 의 실제 취소 표현(필드명/값)이 문서 가정과 다르면 취소를 여전히 accepted 로 오판해 갇힘이 재현된다.
    • 완화 방안: 실 응답 샘플(또는 KIS 명세)로 cncl_yn 등 필드를 확정하고, 미지 응답은 unknown 으로 보수 처리하되 OQ-2 의 Alert-only 워치독으로 무한 갇힘을 가시화하는 안전망을 둔다.
  • R-2 (Medium): 외부 취소 → 롤백 → 재매도가 반복되면(운영자가 계속 취소) safety-sell 이 무한 재매도 루프를 돌 수 있다.
    • 완화 방안: dcy-010(REQ-052) 의 per-slot 재시도 쿨다운/영속 거부 경고가 재매도 빈도를 제어하는지 확인하고, 필요 시 cancelled 도 쿨다운 트리거에 포함한다.
  • R-3 (Medium, OQ-1 A안으로 완화): 부분 체결 후 취소를 단순 롤백하면 이미 팔린 수량을 다시 팔아 과매도가 날 수 있다.
    • 완화 방안: OQ-1 A안(체결분 원장 기록 + 슬롯 qty 차감 + 잔여 HOLDING 복귀)으로 잔여분만 재매도되어 과매도가 구조적으로 차단된다. 부분 체결 회계 정확성은 REQ-018(원장)·REQ-031(포지션 정합) 검증과 연계해 보장한다.

가정

아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.

  • A-1: dcy-012 구현이 완료되어 슬롯 가격 필드가 limit_price 로 통일되고 HOLDING 진입 시 clear 되므로, 취소 후 롤백된 슬롯의 재매도는 시장가로 나가 체결성이 보장된다.
  • A-2: FillStatus.is_terminal_reject 가 이미 cancelled 를 포함하고 _rollback 이 PENDING_SELL → HOLDING 을 수행하므로, KIS 어댑터가 cancelled 만 정확히 반환하면 application 경로 변경 없이 회복이 성립한다.
  • A-3: paper 브로커는 이미 취소를 올바르게 처리하므로 본 변경은 KIS 어댑터(+필요 시 부분취소/워치독)에 국한된다.

오픈 질문

답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.

  • OQ-1: 부분 체결 후 취소 처리 정책 — 체결분을 원장에 기록하고 잔여 수량만 정합(예: HOLDING 잔량 갱신) 처리하는가, 아니면 다른 규칙을 쓰는가?
    • 상태: Answered (2026-06-08, 사용자 결정 — A안: 한 번에 올바르게(정확 회계))
    • 결정: 부분 체결 후 취소 감지 시 ① 체결분(ccld_qty)을 원장에 1회 기록, ② 슬롯 qty 를 ccld_qty 만큼 차감, ③ 잔여 qty 로 HOLDING 복귀(재매도는 잔여분만)한다. avg_price(주당 원가)는 그대로 유지되어 잔여 포지션도 정합하며, 과매도·원장 누락을 동시에 방지한다. 단순 롤백(C)·격리 후속(B)은 미채택.
    • 반영 위치: FR-2, 4. 변경 항목, 영향 범위, R-3
  • OQ-2: pending stale 워치독/타임아웃을 이번 주기에 포함하는가, 후속으로 분리하는가? 포함 시 임계 기준은?
    • 상태: Answered (2026-06-08, 사용자 결정 — 포함, Alert-only)
    • 결정: pending 주문이 임계 시간을 초과해 머물면 stale 로 감지해 WARN 로그·메트릭으로 가시화만 하고 슬롯/주문 상태는 변경하지 않는다(Alert-only). cncl_yn 매핑이 틀려도(R-1) 무한 갇힘이 silent 가 아니라 운영자에게 노출되는 안전망. 타임아웃 시 자동 롤백/취소(auto-remediation)는 정상 slow fill·지정가 대기와의 상호작용 및 KIS 주문 취소 능력이 필요해 후속으로 분리. 임계는 configurable(시장가 매도는 짧게, 지정가 매도는 관대하게 또는 단일 보수적 임계).
    • 반영 위치: FR-3, 범위 경계, R-1 완화
  • OQ-3: 거버넌스 경로 — 기존 REQ(REQ-012 KIS 어댑터, REQ-014 reconciliation 등)의 change-req 로 처리할지, 신규 REQ 로 추적할지?
    • 상태: Answered (2026-06-08, 사용자 결정 — change-req 우선)
    • 결정: 기존 Implemented REQ 본문 수정(change-req)으로 처리한다. change-req 대상 — REQ-012(KIS 어댑터: cncl_yn 파싱 + cancelled 매핑), REQ-013(주문 집행 루프: 부분 체결 회계 — qty 차감 + 잔여 HOLDING 복귀), REQ-018(체결→원장 기록: 부분 체결분 1회 기록), REQ-031(포지션 정합: 잔여 포지션 정합 연계), REQ-014(주문 핸드오프 durability + reconciliation: pending stale 워치독 Alert-only), REQ-015(브로커/집행 baseline 문서 정합: interface-contract/runtime-flows 갱신). 원칙적으로 신규 REQ 는 생성하지 않는다 — 단 워치독 임계 env 설정이 별도 추적을 요하면 REQ 정제에서 소형 config 신규 REQ 를 둘 수 있다(조건부).
    • 반영 위치: 1. 거버넌스 해석, R-1 완화 방안, 8. 확인 체크

오픈 질문 처리 기준

  • Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.
  • Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.
  • Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.
  • Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.

7. 초기 성공 기준

이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.

  • S-1: 외부 취소된 매도 주문이 다음 tick 에 cancelled 로 감지되어 슬롯이 HOLDING 으로 복귀하고 broker_order_id 가 비워진다(영구 갇힘 0건).
  • S-2: 취소된(죽은) 주문에 대한 추가 KIS 폴링이 발생하지 않는다.
  • S-3: 부분 체결 후 취소 시 체결분이 원장에 1회 기록되고 잔여 포지션이 실제 잔고와 일치한다(과매도/이중기록 0건).
  • S-4: pending 주문이 임계 시간을 초과하면 워치독이 WARN/메트릭으로 가시화한다(미지 원인 무한 갇힘이 silent 로 남지 않음). 슬롯/주문 상태는 변경하지 않는다.

측정 방식 및 데이터 출처

각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.

  • S-1 측정 방식: KIS 어댑터 단위 테스트(취소 응답 fixture → cancelled) + 집행 통합 테스트(롤백→HOLDING) 통과 / 데이터 출처: poll_fill 테스트, 슬롯 상태 스냅샷, inquire-daily-ccld 응답 fixture
  • S-2 측정 방식: 취소 감지 후 해당 slot 의 poll 호출 중단 확인 / 데이터 출처: 폴링 호출 로그/카운터
  • S-3 측정 방식: 부분 체결+취소 시나리오 테스트에서 원장 1건·잔여 수량 정합 확인 / 데이터 출처: ledger_outbox/포지션 정합(REQ-031) 검증, 슬롯 qty
  • S-4 측정 방식: 임계 초과 pending 주입 테스트에서 WARN/메트릭 발생 및 상태 미변경 확인 / 데이터 출처: 워치독 테스트, 데몬 로그/메트릭, 슬롯 상태 스냅샷

8. REQ로 넘기기 전 확인 체크

REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.

  • 범위(In Scope/Out of Scope) 확정
    • 기준: 부분취소 정책(OQ-1 A안)·워치독 포함 여부(OQ-2 Alert-only)·거버넌스(OQ-3) 모두 확정됨
  • 성공 지표의 측정 방식/데이터 출처 확정
    • 기준: S-1~S-4 의 테스트/검증 출처가 실제 실행 가능한 형태로 지정됨
  • High 영향 리스크 우선순위 및 해소 책임자 지정
    • 기준: R-1(취소 필드 규약 확인)의 change-req 대상(REQ-012/013/018/031/014/015)이 OQ-3 으로 확정됨. 해소 실무 책임자 배정·DATA(취소 필드 확인)는 REQ/batch planning 단계로 넘김(비차단).
  • 모든 오픈 질문(OQ) Open 상태 없음 확인
    • 기준: OQ-1~OQ-3 모두 Answered, Open 0개
  • Freeze 확정 담당자(CONFIRMED_BY) 지정
    • 기준: Confirmed By = Justin (사람 승인자 지정 완료)

9. 파일 처리 결과

이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.

  • 처리 결과: 생성
  • 생성 경로: docs/discovery/dcy-013_20260608_kis-external-cancel-pending-sell-stuck.md
  • 참조 문서:
    • GitHub issue #9 (fourblocks2020/trex-core) — KIS 외부 취소 시 pending_sell 갇힘
    • docs/discovery/dcy-003_20260604_broker-execution-and-outbox.md — 집행 폴/롤백 경로 도입 근거
    • docs/discovery/dcy-012_20260608_sell-order-pricing-entry-price-bug.md — 매도 가격 버그(같은 pending_sell 갇힘 증상의 다른 원인, A-1)
    • docs/discovery/dcy-010_20260607_safety-sell-persistent-rejection-backoff.md — per-slot 재시도 쿨다운(재매도 루프 완화, R-2)
    • trex_core/adapters/broker/kis.py:163-208 — poll_fill 취소 미파싱 갭

10. 사용자 결정 필요 항목 요약

사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.

DECIDE

  • (없음 — OQ-1/OQ-2 확정으로 해소)

결정 완료(2026-06-08): OQ-1 부분 체결 후 취소 = A안(체결분 원장 기록 + 슬롯 qty 차감 + 잔여 HOLDING 복귀, 정확 회계) / OQ-2 워치독 = 포함(Alert-only: WARN/메트릭 가시화, auto-remediation 후속). 결정 항목에서 제외됨.

CONFIRM

  • 없음 — 거버넌스 경로는 OQ-3 으로 확정됨(REQ-012/013/018/031/014/015 change-req, 신규 REQ 원칙적 없음).

DATA

  • (R-1 연계, REQ/delivery 단계 확인) KIS inquire-daily-ccld 응답의 실제 취소 표현(필드명 cncl_yn 등·값 규약). 구현/검증 단계에서 실 응답·KIS 명세로 확정할 데이터이며, 미지 응답은 unknown 보수 처리 + 워치독 가시화로 안전망이 있어 Discovery confirm 을 차단하지 않는다.

11. Discovery Freeze

REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.

섹션 참조

Freeze 플래그

  • Handoff Decision: 승인
  • Handoff Rationale: confirm-discovery 완료. 오픈 질문 OQ-1~OQ-3 모두 Answered (부분 체결 후 취소=A안 정확 회계 / 워치독=포함 Alert-only / 거버넌스=REQ-012/013/018/031/014/015 change-req, 신규 REQ 원칙적 없음). C 유형 플레이스홀더 0개, 저장소 사실관계 일치. DATA(KIS 취소 필드)는 REQ/delivery 단계 확인 비차단. REQ 초안 작성 인계 가능.
  • Ready for REQ Drafting: true
  • Confirmed By: Justin Ko
  • Confirmed At (KST): 2026-06-08 14:10 KST