docs(req): dcy-008 kill-switch confirm-discovery + REQ-043~047 (Approved)

dcy-008(비상 정지/kill-switch) OQ-2(별도 테이블/store)·OQ-4(수동 해제
resume_kill_switch) 결정 → confirm-discovery(confirmed) → draft-req →
confirm-req(5개 Approved).

- REQ-043 (Interface): trex.pause.req → trex.control.req 제어 채널 + action dispatch (OQ-1)
- REQ-044 (Data): day-scoped killswitch_exclusion 테이블 + store + 005 마이그레이션 (OQ-2)
- REQ-045 (Interface): kill_switch 실행 — 범위별 holding 순차 sell() + idempotency + 이력 (NFR-1/2 흡수)
- REQ-046 (Interface): 당일 제외 masking + 다음 거래일 자동복귀 + resume_kill_switch (OQ-4, NFR-3 흡수)
- REQ-047 (Documentation): baseline 3문서 정합

OQ-3(pending_buy 롤백)은 REQ Deferred. srs index Next ID REQ-048, Register +5,
요약 갱신. dcy-008 생성된 REQ 참조 기록.

dcy-009(멀티 인스턴스 RabbitMQ, draft)는 별도 주제로 제외.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 11:29:31 +09:00
co-authored by Claude Opus 4.8
parent 6fda381f62
commit c912c08071
8 changed files with 638 additions and 45 deletions
@@ -1,13 +1,13 @@
# 0. 문서 상태
- 상태: draft
- 상태: confirmed
- 문서 ID: dcy-008_20260607_emergency-stop-kill-switch
- 이슈명: 비상 정지/강제 청산(kill-switch) — portfolio/전역 슬롯 청산 + 당일 전략 제외
- 작성 시각(KST): 2026-06-07
- 마지막 갱신 시각(KST): 2026-06-07
- 마지막 갱신 시각(KST): 2026-06-07 11:11 (draft-req: REQ-043~047 생성)
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: 없음
- 생성된 REQ 참조: REQ-043, REQ-044, REQ-045, REQ-046, REQ-047
# 1. 계획 상태 요약
@@ -52,17 +52,18 @@
# 4. 이번에 정의할 변경
- **kill-switch 트리거 진입점 추가**: 운영자가 RPC 메시지(`trex.pause.req` 확장 또는 신규 채널) 또는 CLI로 kill-switch를 발동하면, 대상 범위(portfolio/전역)의 모든 holding 슬롯에 `SlotService.sell()`을 순차 호출한다.
- **kill-switch 트리거 진입점 추가**: 운영자가 RPC 메시지(`trex.control.req`, `action: "kill_switch"`) 또는 CLI로 kill-switch를 발동하면, 대상 범위(portfolio/전역)의 모든 holding 슬롯에 `SlotService.sell()`을 순차 호출한다. 기존 `trex.pause.req`를 `trex.control.req`로 개념 확장하고 action 필드 기반 dispatch로 구현한다(새 큐 불필요).
- **day-scoped 전략 제외 기능 추가**: kill-switch 발동 후 대상 범위 자산을 당일 전략 실행에서 제외한다. snapshot RPC 응답의 masking 소스에 "kill-switch 당일 제외"를 추가한다. 다음 거래일 데몬 부팅 시 자동 복귀한다.
- **당일 제외 상태 영속화**: kill-switch 당일 제외 상태를 데몬 재시작 후에도 유지하기 위해 DB에 영속한다(pause_store 확장 또는 별도 테이블 — OQ-2).
- **당일 제외 상태 영속화**: kill-switch 당일 제외 상태를 데몬 재시작 후에도 유지하기 위해 DB에 영속한다. **별도 테이블/store 어댑터를 신설**한다(OQ-2 Answered) — `snapshot_pause`(영구 pause)와 분리하고 `trading_date` 키로 day-scoped 표현. 다음 거래일 부팅 시 자동 무효.
- **수동 해제(resume) 지원**: 운영자가 같은 거래일 내에 kill-switch 당일 제외를 해제할 수 있도록 `trex.control.req` 에 `action: "resume_kill_switch"`(범위: portfolio/전역)를 추가한다(OQ-4 Answered). 해당 범위의 day-scoped 제외 row 를 삭제해 정상 매매를 재개한다. 단, 이미 청산된 슬롯은 되돌리지 않는다(매도 비가역).
## 영향 범위
- 코드 영향:
- `trex_core/domain/slot/service.py`: kill-switch 발동 시 복수 슬롯에 sell()을 순차 호출하는 진입점(메서드 또는 헬퍼)
- `trex_core/application/messaging_handlers.py`: kill-switch 명령 처리 handler 추가(RPC 채널 결정 이후)
- `trex_core/application/messaging_handlers.py`: `trex.control.req` action dispatch — kill-switch handler 추가
- `trex_core/adapters/persistence/postgresql.py` 또는 신규 어댑터: day-scoped 제외 상태 영속 read/write
- `trex_core/runtime/daemon.py`: kill-switch RPC consumer 스레드 추가 또는 기존 pause RPC 확장
- `trex_core/runtime/daemon.py`: pause consumer를 control consumer(`trex.control.req`)로 확장 — action 기반 dispatch
- `trex_core/application/portfolio.py` 또는 snapshot handler: masking 소스에 "kill-switch 당일 제외" 추가
- 문서 영향:
- `docs/interface-contract.md`: kill-switch RPC 메시지 계약(payload 구조, 대상 범위, 응답 구조)
@@ -70,7 +71,7 @@
- `docs/project-structure.md`: kill-switch 관련 신규 모듈/handler 반영
- 운영 영향:
- DB 스키마: day-scoped 제외 상태 영속 컬럼 또는 테이블 추가(additive)
- 기존 pause RPC(trex.pause.req) 채널 확장 또는 신규 채널 추가(OQ-1)
- `trex.pause.req` → `trex.control.req` 개념 확장. kill-switch는 `action: "kill_switch"` 필드로 dispatch(새 큐 불필요). daemon.py의 pause consumer 스레드를 control consumer로 교체.
# 5. 요구사항 목록
@@ -94,7 +95,7 @@
- In Scope
- holding 슬롯 즉시 청산 (portfolio/전역 단위, `SlotService.sell()` 재사용)
- 당일 전략 실행 제외 + 다음 거래일 자동 복귀 (day-scoped, 영속 필요)
- kill-switch 트리거 표면: RPC 메시지 (CLI는 REQ 단계에서 결정)
- kill-switch 트리거 표면: `trex.control.req` RPC, `action: "kill_switch"` 메시지 (CLI는 REQ 단계에서 결정)
- kill-switch 발동 후 당일 추가 매수 거부 (masking 소스 확장)
- kill-switch 발동 이력 로깅
- Out of Scope
@@ -110,8 +111,7 @@
- R-1 (Medium): kill-switch 발동 시 다수 슬롯에 순차 sell()을 호출하면 execution worker FIFO 큐에 부하가 집중된다. 슬롯 수가 많을 경우 처리 지연이 발생할 수 있다.
- 완화 방안: sell() 호출은 PENDING_SELL 전이만 수행하므로 빠르다(DB write 1회). execution worker는 기존 순차 처리 유지. 슬롯 수 10 미만 운영 환경 기준으로 NFR-1 허용 지연 설정.
- R-2 (Medium): 당일 제외 상태 영속 방식 미결정(pause_store 확장 vs 별도 테이블). pause와 의미 충돌 시 마스킹 로직 복잡도 증가.
- 완화 방안: OQ-2에서 방식을 결정한다. pause는 "resume 전까지 유지(persistent)"이고 kill-switch 제외는 "당일만(day-scoped)"이라 별도 컬럼 또는 테이블로 분리를 권장한다.
- R-2 (해소): 당일 제외 상태 영속 방식 — **별도 테이블/store 신설로 결정**(OQ-2 Answered). pause는 "resume 전까지 유지(persistent)", kill-switch 제외는 "당일만(day-scoped, `trading_date` 키)"으로 테이블 분리 → 의미 충돌 없음, 기존 pause 마스킹 코드 무영향.
- R-3 (Low): kill-switch 발동 중 브로커 오류로 일부 슬롯의 sell()이 실패하거나 지연될 수 있다.
- 완화 방안: sell() → PENDING_SELL 전이 성공 시 기존 outbox retry 경로가 eventual consistency를 보장한다. 발동 이력(FR-6)으로 미처리 슬롯 추적 가능.
- R-4 (Low): kill-switch와 자율 안전 매도(dcy-007)가 동시에 같은 슬롯에 sell()을 호출하면 중복 전이가 발생할 수 있다.
@@ -127,21 +127,23 @@
## 오픈 질문
- OQ-1: kill-switch 트리거 표면 — 기존 `trex.pause.req` 채널에 `action: "kill_switch"` 메시지를 추가할지, 신규 채널(`trex.killswitch.req`)을 별도로 열지?
- 상태: Open
- 처리 방안: confirm-discovery 단계에서 Justin Ko가 결정. 채널 재사용 시 RabbitMQ 큐 추가 불필요하나 pause 핸들러 확장 필요; 신규 채널 시 명확한 관심사 분리.
- 종료 조건: confirm-discovery 완료 전 Justin Ko 결정 또는 REQ 초안 단계에서 Deferred 처리.
- 상태: Answered
- 결정: `trex.pause.req` → `trex.control.req` 개념 확장. kill-switch는 `action: "kill_switch"` 필드로 라우팅. 새 큐 불필요. 기능마다 채널을 추가하면 consumer 스레드/커넥션이 기능 수에 비례해 증가하므로 단일 제어 채널 + action discriminator 패턴을 채택한다.
- 반영 위치: # 4 변경 정의, # 4 영향 범위 운영 영향, # 5 범위 경계 In Scope
- OQ-2: 당일 제외 상태 영속 방식 — `PostgreSQLPauseStore`(pause_store)를 확장해 day-scoped 컬럼을 추가할지, 별도 테이블/어댑터를 신설할지?
- 상태: Open
- 처리 방안: confirm-discovery 단계에서 결정. pause_store 확장 시 DB 마이그레이션 1건; 별도 테이블 시 명확한 분리.
- 종료 조건: confirm-discovery 완료 전 결정 또는 REQ 단계 Deferred.
- 상태: Answered
- 결정: **별도 테이블/어댑터를 신설**한다. kill-switch 당일 제외는 `trading_date` 키로 day-scoped 표현이 자연스럽고, 기존 `snapshot_pause`(portfolio_id PK, resume까지 영구·날짜 없음)와 의미가 달라 같은 테이블에 섞으면 마스킹/만료 로직 복잡도가 올라간다(R-2). 신규 테이블(예: `killswitch_exclusion(portfolio_id, trading_date, actor, ...)`) + 전용 store 어댑터로 관심사를 분리하고, snapshot 마스킹은 `mask = pending | warning | pause | killswitch_today`로 합성한다. 기존 pause 코드는 무영향.
- 반영 위치: # 4 변경 정의(당일 제외 상태 영속화), # 4 영향 범위(신규 테이블/마이그레이션 + store 어댑터), # 6 R-2 완화, # 5 범위 경계
- 종료 조건: 충족(REQ 단계에서 정확한 테이블 컬럼/만료 기준 = trading_date 경과 자동 무효 상세화).
- OQ-3: kill-switch 발동 시 `pending_buy` 상태 슬롯 처리 — 현재 진행 중인 매수를 무시하고 HOLDING이 된 이후에 청산하도록 기다릴지, 즉시 롤백(PENDING_BUY→IDLE) 처리를 별도로 추가할지?
- 상태: Deferred → REQ 단계
- 처리 방안: PENDING_BUY 롤백은 execution 루프와 상호작용이 복잡하므로 REQ 단계에서 상세 설계. 기본 구현은 HOLDING 슬롯만 대상.
- 종료 조건: REQ 초안 작성 시 pending_buy 범위 명시.
- OQ-4: 전역 halt 수동 해제 지원 여부 — kill-switch 발동 후 같은 거래일 내에 운영자가 당일 제외를 해제하고 정상 매매를 재개할 수 있어야 하는가?
- 상태: Open
- 처리 방안: confirm-discovery 단계에서 Justin Ko 결정. 해제 지원 시 `resume_kill_switch` action 추가 필요.
- 종료 조건: confirm-discovery 완료 전 Justin Ko 결정.
- 상태: Answered
- 결정: **수동 해제를 지원한다.** 운영자가 같은 거래일 내에 kill-switch 당일 제외를 해제하고 정상 매매를 재개할 수 있어야 한다. `trex.control.req` 에 `action: "resume_kill_switch"`(범위: portfolio/전역) 를 추가하고, 해당 범위의 day-scoped 제외 row(OQ-2 신규 테이블)를 삭제(또는 무효화)한다. 해제는 "당일 제외"만 풀며 이미 청산된 슬롯을 되돌리지 않는다(매도는 비가역).
- 반영 위치: # 4 변경 정의(수동 해제 action), # 4 영향 범위(control RPC handler), # 5 범위 경계 In Scope, # 10 DECIDE
- 종료 조건: 충족(REQ 단계에서 `resume_kill_switch` payload/응답 + 권한/감사 상세화).
### 오픈 질문 처리 기준
@@ -164,16 +166,16 @@
# 8. REQ로 넘기기 전 확인 체크
- [ ] 범위(In Scope/Out of Scope) 확정
- 기준: OQ-1(트리거 표면), OQ-2(영속 방식), OQ-4(수동 해제 여부) 결정 또는 Deferred 처리 완료
- [ ] 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-1~S-4 각각 단위 테스트 또는 e2e 근거 확정
- [ ] High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1(큐 부하), R-2(영속 방식) 완화 방안 REQ 단계 인계 여부 확인
- [ ] 모든 오픈 질문(OQ) `Open` 상태 없음 확인
- 기준: OQ-1, OQ-2, OQ-4 결정 완료 또는 REQ Deferred 처리 완료 (OQ-3은 이미 Deferred)
- [ ] Freeze 확정 담당자(CONFIRMED_BY) 지정
- 기준: Justin Ko 확인
- [x] 범위(In Scope/Out of Scope) 확정
- OQ-1/2/4 Answered, OQ-3 REQ Deferred. scope = portfolio+전역 둘 다(FR-4). 확정.
- [x] 성공 지표의 측정 방식/데이터 출처 확정
- S-1~S-4 각각 단위 테스트/e2e 근거 명시(# 7 측정 방식). 확정.
- [x] High 영향 리스크 우선순위 및 해소 책임자 지정
- R-1(큐 부하) 완화 = 순차 sell()·N<10 가정으로 NFR-1 인계, R-2(영속 방식) 해소(별도 테이블). REQ 단계 인계.
- [x] 모든 오픈 질문(OQ) `Open` 상태 없음 확인
- OQ-1/2/4 Answered, OQ-3 Deferred → `Open` 없음.
- [x] Freeze 확정 담당자(CONFIRMED_BY) 지정
- Confirmed By = Justin.
# 9. 파일 처리 결과
@@ -189,18 +191,17 @@
## DECIDE
- {{DECIDE_TRIGGER_SURFACE}}: kill-switch 트리거 표면 — `trex.pause.req` 채널 확장(`action: "kill_switch"`) vs 신규 채널(`trex.killswitch.req`) (OQ-1)
- {{DECIDE_PERSIST_METHOD}}: 당일 제외 상태 영속 방식 — pause_store 확장(컬럼 추가) vs 별도 테이블 신설 (OQ-2)
- {{DECIDE_MANUAL_RESUME}}: 같은 거래일 내 kill-switch 당일 제외 수동 해제 지원 여부 (OQ-4)
- ✅ DECIDE_PERSIST_METHOD (OQ-2, Answered): 당일 제외 상태 영속 방식 = **별도 테이블/store 신설**(`snapshot_pause`와 분리, `trading_date` day-scoped).
- ✅ DECIDE_MANUAL_RESUME (OQ-4, Answered): 수동 해제 **지원** — `trex.control.req action: "resume_kill_switch"` 추가, day-scoped 제외 해제(청산된 슬롯은 비가역).
## CONFIRM
- {{CONFIRM_SCOPE_PORTFOLIO_AND_GLOBAL}}: portfolio 단위와 전역 단위 둘 다 이번 Discovery 범위에 포함하는지, 혹은 전역만 우선 구현할지 확인
- {{CONFIRM_PENDING_BUY_DEFERRED}}: pending_buy 슬롯 롤백은 REQ 단계로 Deferred 처리해도 무방한지 확인 (OQ-3)
- ✅ CONFIRM_SCOPE_PORTFOLIO_AND_GLOBAL: **portfolio 단위 + 전역 단위 둘 다 포함**. 본문 FR-4("portfolio 단위와 전역 단위 둘 다 구분해 지원") + In Scope("portfolio/전역 단위") + 이슈명에서 이미 확정 — 동일하게 유지.
- ✅ CONFIRM_PENDING_BUY_DEFERRED: **REQ 단계 Deferred로 처리(동의)**. OQ-3(Deferred → REQ 단계) + Out of Scope("pending_buy 슬롯의 롤백 처리 — OQ-3 Deferred")에 비차단으로 명시됨. 기본 구현은 HOLDING 슬롯만 대상.
## DATA
- {{DATA_SLOT_COUNT_UPPER_BOUND}}: 실 운영 환경의 최대 동시 holding 슬롯 수 (NFR-1 지연 허용치 산정 기준)
- (비차단, REQ 단계 계측) DATA_SLOT_COUNT_UPPER_BOUND: 실 운영 환경의 최대 동시 holding 슬롯 수. A-4 가정(통상 10 미만)으로 NFR-1(N×100ms+5s) 산정 충분. 실측 상한은 REQ acceptance/verification 단계에서 확정 — Discovery confirm 차단 아님.
# 11. Discovery Freeze
@@ -214,8 +215,8 @@
## Freeze 플래그
- Handoff Decision: 보류
- Handoff Rationale: 초기 Discovery 초안 생성 완료. OQ-1(트리거 표면), OQ-2(영속 방식), OQ-4(수동 해제 여부) 미결 — confirm-discovery에서 Justin Ko 결정 후 REQ 초안 작성 가능.
- Ready for REQ Drafting: false
- Confirmed By: TBD
- Confirmed At (KST): TBD
- Handoff Decision: 승인
- Handoff Rationale: OQ-1(trex.control.req+action), OQ-2(별도 테이블/store 신설), OQ-4(수동 해제=resume_kill_switch) Answered, OQ-3(pending_buy) REQ Deferred. CONFIRM(scope=portfolio+전역=FR-4, pending_buy=REQ Deferred) 본문 근거로 확정, DATA(slot 수 상한)는 REQ 단계 계측(비차단). 코드 사실관계(SlotService.sell REQ-036, trex.pause.req) 일치, baseline 모순 없음. REQ 초안 작성 가능.
- Ready for REQ Drafting: true
- Confirmed By: Justin
- Confirmed At (KST): 2026-06-07 11:11
+1 -1
View File
@@ -13,4 +13,4 @@
| dcy-005_20260604_portfolio-hub-asset-snapshot-api | 20260604 | portfolio-hub 종목 스냅샷 read API — 전략 모듈에 전략 실행 대상 자산 리스트 제공 | [Discovery](./dcy-005_20260604_portfolio-hub-asset-snapshot-api.md) | confirmed |
| dcy-006_20260605_strategy-module-rabbitmq-transport | 20260605 | trex-core ↔ 전략 모듈 통신 transport — RabbitMQ 도입 (스냅샷 read + intent 제출 + 이벤트) | [Discovery](./dcy-006_20260605_strategy-module-rabbitmq-transport.md) | confirmed |
| dcy-007_20260606_core-autonomous-safety-sell | 20260606 | core 자율 안전 매도 — stop-loss·시간 만기 자동 트리거 | [Discovery](./dcy-007_20260606_core-autonomous-safety-sell.md) | confirmed |
| dcy-008_20260607_emergency-stop-kill-switch | 20260607 | 비상 정지/강제 청산(kill-switch) — portfolio/전역 슬롯 청산 + 당일 전략 제외 | [Discovery](./dcy-008_20260607_emergency-stop-kill-switch.md) | draft |
| dcy-008_20260607_emergency-stop-kill-switch | 20260607 | 비상 정지/강제 청산(kill-switch) — portfolio/전역 슬롯 청산 + 당일 전략 제외 | [Discovery](./dcy-008_20260607_emergency-stop-kill-switch.md) | confirmed |
@@ -0,0 +1,116 @@
# req-044: kill-switch day-scoped 제외 store + 테이블 + 마이그레이션
- Status: Approved
- Type: Data
- Priority: High
- Owner: project maintainers
## Intent
kill-switch 발동 시 대상 범위(portfolio/전역)를 **당일(day-scoped) 전략 실행에서 제외**하는 상태를 데몬 재시작 후에도 유지하기 위해 영속화한다. 기존 `snapshot_pause`(portfolio_id PK, resume 전까지 영구, 날짜 없음)와 의미가 다르므로(당일만, `trading_date` 키), **별도 테이블 + 전용 store 어댑터를 신설**한다(dcy-008 OQ-2 Answered). 다음 거래일 부팅 시 자동 무효된다.
## Requirement
- 신규 테이블(예: `killswitch_exclusion`)을 추가하는 additive 마이그레이션을 작성한다. 최소 컬럼: `portfolio_id`(전역 제외 표현 포함), `trading_date`, `actor`, `created_at`.
- 전역(global) 제외 표현 방식(예: `portfolio_id = '*'` sentinel 또는 별도 scope 컬럼)은 구현 시 결정한다(Notes).
- PK 또는 unique 제약은 `(portfolio_id, trading_date)` 로 동일 거래일 중복 제외를 멱등 처리한다.
- 전용 store 어댑터(예: `PostgreSQLKillSwitchStore`)가 아래를 제공한다: `exclude(portfolio_id|global, trading_date, actor)`, `clear(portfolio_id|global, trading_date)`(수동 해제, REQ-046), `list_excluded(trading_date) -> set`.
- `list_excluded(trading_date)` 는 **해당 거래일** 의 제외 항목만 반환한다. 다른 날짜 row 는 자동으로 결과에서 제외된다(day-scoped). 과거 row 정리(삭제)는 선택이며 조회가 trading_date 로 필터링되므로 정합에 영향 없다.
- 기존 `snapshot_pause` / `PostgreSQLPauseStore` 는 변경하지 않는다(관심사 분리).
## Acceptance Criteria
1. Given 마이그레이션 적용, When 스키마를 확인하면, Then `killswitch_exclusion` 테이블이 `(portfolio_id, trading_date, actor, created_at)` 컬럼과 `(portfolio_id, trading_date)` 멱등 제약으로 존재한다.
2. Given 마이그레이션을 2회 적용, When 재적용하면, Then `IF NOT EXISTS` 패턴으로 오류 없이 멱등하다(기존 데이터 보존).
3. Given `exclude("pf-A", D)`, When `list_excluded(D)`, Then `{"pf-A"}` 를 포함한다.
4. Given `exclude("pf-A", D)`, When `list_excluded(D+1)`(다음 거래일), Then `pf-A` 가 포함되지 않는다(day-scoped 자동 무효).
5. Given 같은 `(pf-A, D)` 로 `exclude` 2회, When 호출하면, Then 멱등(중복 row 없음, 오류 없음).
6. Given `exclude("pf-A", D)` 후 `clear("pf-A", D)`, When `list_excluded(D)`, Then `pf-A` 가 더 이상 포함되지 않는다(수동 해제, REQ-046).
7. Given 전역 제외, When `exclude` 후 `list_excluded(D)`, Then 전역 sentinel 이 결과에 포함되어 호출자가 전체 제외로 해석할 수 있다.
## Impacted Area
- Docs:
- `docs/project-structure.md` — 신규 테이블/store 모듈 반영 (REQ-047 처리)
- Modules:
- `trex_core/adapters/persistence/sql/005_create_killswitch_exclusion.sql` (신규, additive)
- `trex_core/adapters/portfolio/killswitch_store.py` 또는 동등 위치 — `PostgreSQLKillSwitchStore`
- Tests:
- store CRUD + day-scoped 조회 + 멱등 + 전역 sentinel 단위/통합 테스트(PG 게이트)
## Notes
- dcy-008 OQ-2 Answered: 별도 테이블/store 신설(snapshot_pause 와 분리).
- 전역 제외 표현(`portfolio_id='*'` vs scope enum 컬럼)은 구현 결정 — masking 소비처(REQ-046)와 계약 일치만 보장하면 됨.
- `trading_date` 기준: dcy-008 의 day-scoped 의미 = "발동 거래일". 거래일 경계(UTC vs KST)는 데몬의 기존 trading_date 관례(UTC date)를 따르되 REQ-045/046 와 일치시킨다.
- BAT-010 R-2(마이그레이션 실 PG round-trip) 선례에 따라 verification 에서 실 PG 적용 확인.
## Change Log
### CHG-20260607-01
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- dcy-008(confirmed) → REQ-044 초안 생성.
#### Intent
- 당일 제외 영속(OQ-2 Answered: 별도 테이블)을 Data REQ 로 정규화.
#### Acceptance Criteria Delta
- Added: AC-1~7 전체
#### Impacted Area Delta
- Docs: project-structure.md (REQ-047)
- Modules: sql/005_create_killswitch_exclusion.sql, killswitch_store.py
- Tests: store CRUD + day-scoped + 멱등
#### 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 로 승인.
### CHG-20260607-02
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- Proposed → Approved (confirm-req).
#### Intent
- 승인 게이트 통과: 필수 필드·구체 AC·Impacted Area·Change Log 완비. dcy-008(confirmed) OQ-2 결정(별도 테이블) 반영. 전역 sentinel 표현은 구현 결정으로 승인 blocker 아님.
#### Acceptance Criteria Delta
- (변경 없음)
#### Impacted Area Delta
- (변경 없음)
#### Delivery Trace Delta
- Batches: none (미할당)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성.
@@ -0,0 +1,113 @@
# req-047: kill-switch baseline 문서 정합
- Status: Approved
- Type: Documentation
- Priority: Medium
- Owner: project maintainers
## Intent
dcy-008(비상 정지/kill-switch) 기능(REQ-043~046)의 구현 완료 후 `docs/interface-contract.md`, `docs/runtime-flows.md`, `docs/project-structure.md` 세 baseline 문서를 최신 아키텍처와 정합시킨다.
## Requirement
- `docs/interface-contract.md` 에 아래를 반영한다:
- `trex.pause.req` → `trex.control.req` 제어 채널 확장 + action 목록(`pause`/`resume`/`list`/`kill_switch`/`resume_kill_switch`) (REQ-043)
- `kill_switch` payload(`scope`, `portfolio_id?`)/응답(`liquidated`) 계약 (REQ-045)
- `resume_kill_switch` payload/응답 계약 (REQ-046)
- snapshot masking 소스에 "kill-switch 당일 제외" 추가 명시 (REQ-046)
- `docs/runtime-flows.md` 에 아래 흐름을 추가한다:
- kill-switch 발동 흐름(control RPC → 범위별 holding 순차 sell() → 당일 제외 표시) (REQ-045)
- 당일 제외 masking / 다음 거래일 자동 복귀 / 수동 resume 흐름 (REQ-046)
- `docs/project-structure.md` 에 아래를 반영한다:
- control consumer(`trex.control.req`) 로의 전환 (REQ-043)
- 신규 `killswitch_exclusion` 테이블 + `005_create_killswitch_exclusion.sql` + kill-switch store 모듈 (REQ-044)
## Acceptance Criteria
1. Given `docs/interface-contract.md` 를 읽을 때, When 제어 채널을 찾으면, Then `trex.control.req` + action 목록(kill_switch/resume_kill_switch 포함)이 명시되어 있다.
2. Given `docs/interface-contract.md` 를 읽을 때, When kill_switch/resume_kill_switch 를 찾으면, Then payload(scope/portfolio_id)와 응답 구조가 명시되어 있다.
3. Given `docs/runtime-flows.md` 를 읽을 때, When kill-switch 관련 흐름을 찾으면, Then 발동(순차 sell()+당일 제외)·masking·자동 복귀·수동 resume 흐름이 서술되어 있다.
4. Given `docs/project-structure.md` 를 읽을 때, When 제어 채널/저장소를 찾으면, Then control consumer 전환 + `killswitch_exclusion` 테이블/store + `005_*.sql` 이 반영되어 있다.
## Impacted Area
- Docs:
- `docs/interface-contract.md`
- `docs/runtime-flows.md`
- `docs/project-structure.md`
- Modules: 없음 (문서 전용)
- Tests: 없음
## Notes
- 이 REQ 는 REQ-043~046 구현 완료 후 batch verification 단계에서 최신 구현 상태를 반영해 수행한다(REQ-042 선례).
- baseline 문서가 없는 갭이 아니라 기존 baseline 갱신이므로 `bootstrap-baseline` 선행 불필요.
## Change Log
### CHG-20260607-01
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- dcy-008(confirmed) → REQ-047 초안 생성.
#### Intent
- kill-switch 구현 후 세 baseline 문서 정합을 Documentation REQ 로 정규화.
#### Acceptance Criteria Delta
- Added: AC-1~4 전체
#### Impacted Area Delta
- Docs: interface-contract.md, runtime-flows.md, project-structure.md
#### 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 로 승인 (REQ-043~046 구현 batch 이후 연계).
### CHG-20260607-02
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- Proposed → Approved (confirm-req).
#### Intent
- 승인 게이트 통과: 필수 필드·구체 AC(1~4)·Impacted Area·Change Log 완비. baseline 정합 문서 REQ로 REQ-043~046 구현 후 verification 단계 수행 예정. 범위와 모순 없음.
#### Acceptance Criteria Delta
- (변경 없음)
#### Impacted Area Delta
- (변경 없음)
#### Delivery Trace Delta
- Batches: none (미할당)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성(REQ-043~046 이후 연계).
@@ -0,0 +1,115 @@
# req-043: trex.control.req 제어 채널 + action dispatch
- Status: Approved
- Type: Interface
- Priority: High
- Owner: project maintainers
## Intent
기존 `trex.pause.req` 단일 목적 큐를 `trex.control.req` 제어 채널로 개념 확장하고, payload `action` 필드 기반 dispatch로 운영자 제어 명령을 단일 채널에서 처리한다. 기능마다 큐/consumer 스레드를 늘리지 않기 위한 단일 제어 채널 + action discriminator 패턴(dcy-008 OQ-1 Answered). 기존 pause/resume/list 동작을 보존하면서 kill-switch(REQ-045)와 resume_kill_switch(REQ-046) 라우팅 진입점을 추가한다.
## Requirement
- 데몬은 단일 제어 큐 `trex.control.req` 를 소비하고 메시지 payload 의 `action` 필드로 핸들러를 분기한다.
- 기존 제어 action(`pause`/`resume`/`list`, REQ-032)의 동작·응답 계약을 그대로 유지한다.
- 신규 action 라우팅을 추가한다: `kill_switch`(REQ-045), `resume_kill_switch`(REQ-046). 본 REQ는 라우팅·메시지 계약 골격만 정의하고 실제 청산/해제 동작은 각 REQ에서 정의한다.
- 알 수 없는 `action` 은 `{status: "error", reason: "unknown_action:<action>"}` 으로 응답한다.
- 기존 `trex.pause.req` consumer 스레드를 control consumer(`trex.control.req`)로 교체한다. 데몬 워커 스레드 총수는 불변(7개 유지).
- 하위호환: `trex.pause.req` 를 사용하던 기존 클라이언트 호환 방식(별칭 큐 유지 vs `trex.control.req` 단일화)은 배포 영향이 있으므로 Notes 에 결정 필요로 남긴다.
## Acceptance Criteria
1. Given `trex.control.req` 에 `{action: "pause", portfolio_id}` 발행, When 처리되면, Then 기존 REQ-032 pause 동작과 동일하게 `snapshot_pause` 에 반영되고 `{status: "ok", paused[], action}` 응답을 반환한다.
2. Given `{action: "resume", portfolio_id}` / `{action: "list"}`, When 처리되면, Then 각각 기존 resume/list 동작과 동일한 응답을 반환한다.
3. Given `{action: "kill_switch", ...}`, When 처리되면, Then kill-switch 핸들러(REQ-045)로 라우팅된다.
4. Given `{action: "resume_kill_switch", ...}`, When 처리되면, Then resume 핸들러(REQ-046)로 라우팅된다.
5. Given `{action: "bogus"}`, When 처리되면, Then `{status: "error", reason: "unknown_action:bogus"}` 를 반환한다.
6. Given 데몬 기동, When 워커 스레드를 확인하면, Then pause consumer 가 control consumer 로 교체되어 총 워커 스레드 수가 7로 불변이다.
## Impacted Area
- Docs:
- `docs/interface-contract.md` — 제어 채널 계약(`trex.control.req` + action 목록) (REQ-047 처리)
- Modules:
- `trex_core/adapters/messaging/topology.py` — `CONTROL_REQ_QUEUE = "trex.control.req"` 추가(또는 `PAUSE_REQ_QUEUE` 대체)
- `trex_core/application/messaging_handlers.py` — `make_control_rpc_handler`(action dispatch) 신설 또는 `make_pause_rpc_handler` 확장
- `trex_core/runtime/daemon.py` — pause consumer → control consumer 교체
- Tests:
- control dispatch 단위 테스트(pause/resume/list 회귀 + kill_switch/resume_kill_switch 라우팅 + unknown action)
## Notes
- dcy-008 OQ-1 Answered: 단일 제어 채널 + action discriminator. 새 큐 추가 없음.
- 하위호환 결정 필요(배포): 기존 `trex.pause.req` 토픽 이름을 유지(별칭)할지, `trex.control.req` 로 단일화하고 전략/운영 클라이언트를 함께 갱신할지 — batch planning/release 단계에서 확정. 현재 CLI pause/resume 는 store 직접 호출이라 영향 없음(RPC 경로만 대상).
- kill_switch/resume_kill_switch 의 payload 상세(scope/portfolio_id)는 REQ-045/046 에서 정의.
## Change Log
### CHG-20260607-01
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- dcy-008(confirmed) → REQ-043 초안 생성.
#### Intent
- kill-switch 트리거 표면(OQ-1 Answered)을 단일 제어 채널 Interface REQ 로 정규화.
#### Acceptance Criteria Delta
- Added: AC-1~6 전체
#### Impacted Area Delta
- Docs: interface-contract.md (REQ-047)
- Modules: topology.py, messaging_handlers.py, daemon.py
- Tests: control dispatch 단위
#### 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 로 승인.
### CHG-20260607-02
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- Proposed → Approved (confirm-req).
#### Intent
- 승인 게이트 통과: 필수 필드·구체 AC·Impacted Area·Change Log 완비. dcy-008(confirmed) 범위·결정(OQ-1/2/4 Answered, OQ-3 Deferred)과 모순 없음. 하위호환(큐 rename)은 batch/release 단계 비핵심 운영 결정으로 승인 blocker 아님.
#### Acceptance Criteria Delta
- (변경 없음)
#### Impacted Area Delta
- (변경 없음)
#### Delivery Trace Delta
- Batches: none (미할당)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성.
@@ -0,0 +1,122 @@
# req-045: kill-switch 실행 — 범위별 holding 즉시 청산 + 이력 로깅
- Status: Approved
- Type: Interface
- Priority: High
- Owner: project maintainers
## Intent
운영자가 `trex.control.req` 에 `action: "kill_switch"` 를 발행하면 대상 범위(portfolio 단위 또는 전역)의 모든 `holding` 슬롯을 즉시 청산한다. 기존 `SlotService.sell()`(REQ-036)을 재사용해 순차 매도를 제출하고, 같은 발동에서 대상 범위를 당일 제외(REQ-044/046)로 표시한다. 자율 안전 매도(dcy-007)와 독립적으로 동작하며, 발동 이력을 로깅한다(dcy-008 FR-1/4/5/6, NFR-1/2).
## Requirement
- `action: "kill_switch"` payload: `{action, scope: "portfolio"|"global", portfolio_id?(scope=portfolio 시 필수), actor?}`.
- 발동 시 대상 범위의 모든 `holding` 슬롯에 `SlotService.sell(actor="kill-switch", reason="emergency_stop")` 을 순차 호출한다.
- scope=portfolio: 해당 `portfolio_id` 의 holding 슬롯만.
- scope=global: 당일 전체 holding 슬롯.
- 이미 `pending_sell` 인 슬롯은 중복 sell 하지 않는다(REQ-036 idempotency).
- 발동과 동시에 대상 범위를 당일 제외로 표시한다(REQ-044 store 의 `exclude(...)` 호출). masking 동작 자체는 REQ-046.
- 발동 이력(actor, 발동 시각, scope, portfolio_id, 처리 슬롯 수)을 데몬 로그에 1건 기록한다.
- 응답: `{status: "ok", scope, portfolio_id?, liquidated: <처리 슬롯 수>}`. scope=portfolio 인데 `portfolio_id` 누락 시 `{status: "error", reason: "portfolio_id_required"}`.
- kill-switch 실행은 자율 안전 매도 루프(dcy-007)와 상태/스레드를 공유하지 않으며 서로 영향을 주지 않는다.
## Acceptance Criteria
1. Given holding 슬롯 N개(전역), When `{action:"kill_switch", scope:"global"}` 처리, Then N개 모두 `holding→pending_sell`(actor=kill-switch, reason=emergency_stop) 전이되고 응답 `liquidated=N`.
2. Given portfolio `pf-A` 에 holding 2개 + `pf-B` 에 holding 1개, When `{action:"kill_switch", scope:"portfolio", portfolio_id:"pf-A"}`, Then `pf-A` 2개만 청산되고 `pf-B` 는 holding 유지.
3. Given 대상 중 이미 `pending_sell` 인 슬롯, When kill_switch 처리, Then 그 슬롯에 중복 sell 호출이 없다(REQ-036 idempotency, transition_log 중복 없음).
4. Given scope=portfolio 인데 `portfolio_id` 누락, When 처리, Then `{status:"error", reason:"portfolio_id_required"}`.
5. Given kill_switch 발동, When 처리 완료, Then 대상 범위가 REQ-044 store 에 당일 제외로 기록된다(`list_excluded(today)` 에 포함).
6. Given kill_switch 발동, When 로그를 확인, Then actor/발동 시각/scope/portfolio_id/처리 슬롯 수를 담은 이력 1건이 기록된다.
7. Given 자율 안전 매도 루프(dcy-007)가 동작 중, When kill_switch 가 발동, Then 두 경로가 독립적으로 동작하며(REQ-036 idempotency 로 충돌 없음) safety-sell 루프가 중단/오류 없이 유지된다.
8. Given holding N개, When kill_switch 처리, Then 전체 sell() 제출 완료까지 지연이 N×100ms + 5s 이내이다(순차, outbox 전송 제외; A-4 N<10 가정).
## Impacted Area
- Docs:
- `docs/runtime-flows.md` — kill-switch 발동 흐름(트리거→순차 sell()→당일 제외 표시) (REQ-047 처리)
- `docs/interface-contract.md` — kill_switch payload/응답 계약 (REQ-047 처리)
- Modules:
- `trex_core/application/messaging_handlers.py` — kill_switch handler(REQ-043 dispatch 하위)
- `trex_core/domain/slot/service.py` 또는 신규 application 서비스 — 범위별 holding 조회 + 순차 sell() 진입점
- REQ-044 store 연동(당일 제외 표시)
- Tests:
- kill_switch handler 단위 테스트(전역/portfolio/idempotency/portfolio_id 누락/이력 로깅/독립성)
## Notes
- NFR-1(지연)·NFR-2(dcy-007 독립)는 본 REQ AC-8/AC-7 로 흡수(별도 REQ 미승격 — 독립 backlog 가치 낮음, dcy-008 정합).
- pending_buy 슬롯 처리는 dcy-008 OQ-3 Deferred → 기본 구현은 HOLDING 만 대상. pending_buy 롤백은 후속(REQ 추가 또는 change-req).
- R-1(큐 부하): sell()은 PENDING_SELL 전이(DB write 1회)로 빠름. execution worker 순차 처리 유지.
- R-3(브로커 오류): sell()→PENDING_SELL 성공 시 기존 outbox retry 가 eventual consistency 보장.
## Change Log
### CHG-20260607-01
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- dcy-008(confirmed) → REQ-045 초안 생성.
#### Intent
- kill-switch 즉시 청산(FR-1/4/5/6)과 NFR-1/2 흡수를 Interface REQ 로 정규화.
#### Acceptance Criteria Delta
- Added: AC-1~8 전체
#### Impacted Area Delta
- Docs: runtime-flows.md, interface-contract.md (REQ-047)
- Modules: messaging_handlers.py, service.py(또는 신규 서비스), REQ-044 store 연동
- Tests: kill_switch handler 단위
#### 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 로 승인.
### CHG-20260607-02
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- Proposed → Approved (confirm-req).
#### Intent
- 승인 게이트 통과: 필수 필드·구체 AC(1~8)·Impacted Area·Change Log 완비. dcy-008(confirmed) 범위와 모순 없음. NFR-1/2 흡수, OQ-3(pending_buy) REQ Deferred 는 비핵심 후속으로 승인 blocker 아님(기본 구현 HOLDING 한정).
#### Acceptance Criteria Delta
- (변경 없음)
#### Impacted Area Delta
- (변경 없음)
#### Delivery Trace Delta
- Batches: none (미할당)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성.
@@ -0,0 +1,121 @@
# req-046: kill-switch 당일 제외 masking + 자동 해제 + 수동 resume
- Status: Approved
- Type: Interface
- Priority: High
- Owner: project maintainers
## Intent
kill-switch 발동(REQ-045)으로 표시된 당일 제외 상태를 snapshot RPC 응답에 반영해 대상 자산을 당일 전략 실행에서 제외한다(추가 매수 차단). 제외는 day-scoped 라 다음 거래일 자동 복귀하며(REQ-044 `trading_date` 키), 운영자는 같은 거래일 내 `action: "resume_kill_switch"` 로 수동 해제할 수 있다(dcy-008 FR-2/3, NFR-3, OQ-4 Answered).
## Requirement
- snapshot RPC 응답 산출 시 masking 소스에 "kill-switch 당일 제외"(REQ-044 `list_excluded(today)`)를 추가한다: `mask = pending | warning | pause | killswitch_today`.
- scope=portfolio 제외는 해당 `portfolio_id` 자산만, 전역 제외는 당일 전체 자산을 마스킹한다.
- 마스킹된 자산은 buyable/held 뷰에 노출되지 않아 당일 추가 매수 의도가 거부된다.
- 당일 제외는 `trading_date` 기준 day-scoped 다. 다음 거래일 첫 조회/부팅 시 `list_excluded(다음 날)` 에 포함되지 않아 자동 복귀한다(별도 해제 동작 불필요).
- 영속성: 데몬 재시작 후에도 같은 거래일이면 masking 이 유지된다(REQ-044 영속, NFR-3).
- 수동 해제: `action: "resume_kill_switch"` payload `{action, scope, portfolio_id?, actor?}` 처리 시 대상 범위의 당일 제외를 해제(REQ-044 `clear(...)`)해 다음 조회부터 정상 매매 대상으로 복귀시킨다.
- resume 은 **당일 제외(매매 차단)만 해제**하며 이미 청산(매도)된 슬롯을 되돌리지 않는다(매도 비가역).
- 응답: `{status: "ok", scope, portfolio_id?}`. scope=portfolio 인데 `portfolio_id` 누락 시 `{status:"error", reason:"portfolio_id_required"}`.
## Acceptance Criteria
1. Given `pf-A` 가 당일 제외(REQ-044)로 표시됨, When snapshot RPC(view=buyable/all) 처리, Then `pf-A` 자산이 응답 assets 에서 마스킹되어 노출되지 않는다.
2. Given 전역 당일 제외 표시, When snapshot RPC 처리, Then 당일 전체 자산이 마스킹된다.
3. Given 당일 제외 표시 후, When 당일 추가 매수 intent 가 해당 자산에 들어오면, Then buyable 마스킹으로 거부/비노출된다.
4. Given `pf-A` 당일(D) 제외, When 거래일 D+1 로 snapshot RPC 처리, Then `pf-A` 가 다시 노출된다(자동 복귀, 별도 resume 불필요).
5. Given `pf-A` 제외 후 데몬 재시작(같은 거래일 D), When snapshot RPC 처리, Then 여전히 마스킹된다(영속, NFR-3).
6. Given `pf-A` 당일 제외 상태, When `{action:"resume_kill_switch", scope:"portfolio", portfolio_id:"pf-A"}` 처리, Then 다음 snapshot RPC 부터 `pf-A` 가 정상 노출되고 응답 `{status:"ok"}`.
7. Given resume_kill_switch scope=portfolio 인데 `portfolio_id` 누락, When 처리, Then `{status:"error", reason:"portfolio_id_required"}`.
8. Given resume_kill_switch 처리, When 이미 청산된 슬롯을 확인, Then 슬롯 상태(pending_sell/closed)는 되돌려지지 않는다(매도 비가역).
## Impacted Area
- Docs:
- `docs/interface-contract.md` — masking 소스에 kill-switch 당일 제외 + resume_kill_switch 계약 (REQ-047 처리)
- `docs/runtime-flows.md` — 당일 제외 masking / 자동 복귀 / 수동 resume 흐름 (REQ-047 처리)
- Modules:
- `trex_core/application/portfolio.py`(또는 snapshot envelope builder) — masking 소스에 `list_excluded(today)` 추가
- `trex_core/application/messaging_handlers.py` — `resume_kill_switch` handler(REQ-043 dispatch 하위) + snapshot 핸들러에 killswitch store 주입
- REQ-044 store 연동(`list_excluded`/`clear`)
- Tests:
- masking 단위 테스트(portfolio/전역/추가매수 거부) + day-scoped 자동 복귀(날짜 mock) + 재시작 영속 + resume 단위
## Notes
- dcy-008 OQ-4 Answered: 수동 해제 지원(`resume_kill_switch`). 자동 복귀(day-scoped)와 병행.
- NFR-3(영속 후 재시작 masking 유지)는 본 REQ AC-5 로 흡수.
- 전역 제외 sentinel 해석은 REQ-044 store 계약을 따른다.
- masking 합성은 기존 pause masking 패턴(`portfolio.py`)을 재사용(A-2).
## Change Log
### CHG-20260607-01
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- dcy-008(confirmed) → REQ-046 초안 생성.
#### Intent
- 당일 제외 masking/자동 복귀/수동 resume(FR-2/3, OQ-4, NFR-3 흡수)을 Interface REQ 로 정규화.
#### Acceptance Criteria Delta
- Added: AC-1~8 전체
#### Impacted Area Delta
- Docs: interface-contract.md, runtime-flows.md (REQ-047)
- Modules: portfolio.py, messaging_handlers.py, REQ-044 store 연동
- Tests: masking + day-scoped + 영속 + resume 단위
#### 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 로 승인.
### CHG-20260607-02
- Date: 2026-06-07
- Author: Justin Ko
#### Change Summary
- Proposed → Approved (confirm-req).
#### Intent
- 승인 게이트 통과: 필수 필드·구체 AC(1~8)·Impacted Area·Change Log 완비. dcy-008(confirmed) OQ-4 결정(resume_kill_switch) 반영, NFR-3 흡수. 범위·결정과 모순 없음.
#### Acceptance Criteria Delta
- (변경 없음)
#### Impacted Area Delta
- (변경 없음)
#### Delivery Trace Delta
- Batches: none (미할당)
- Releases: none
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: suggest-batch-reqs / draft-batch 로 delivery 편성.
+8 -3
View File
@@ -74,7 +74,7 @@
## Next Requirement ID
- Current: `REQ-043`
- Current: `REQ-048`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -123,11 +123,16 @@
| REQ-040 | update_thresholds intent RPC 액션 | Interface | Implemented | High | project maintainers | [req-040](./Interface/req-040_update-thresholds-intent-rpc.md) |
| REQ-041 | safety-sell 환경 설정 — 5종 env var | Configuration | Implemented | High | project maintainers | [req-041](./Configuration/req-041_safety-sell-env-config.md) |
| REQ-042 | safety-sell baseline 문서 정합 | Documentation | Implemented | Medium | project maintainers | [req-042](./Documentation/req-042_safety-sell-baseline-alignment.md) |
| REQ-043 | trex.control.req 제어 채널 + action dispatch | Interface | Approved | High | project maintainers | [req-043](./Interface/req-043_control-channel-action-dispatch.md) |
| REQ-044 | kill-switch day-scoped 제외 store + 마이그레이션 | Data | Approved | High | project maintainers | [req-044](./Data/req-044_killswitch-exclusion-store-and-migration.md) |
| REQ-045 | kill-switch 실행 — 범위별 holding 즉시 청산 + 이력 | Interface | Approved | High | project maintainers | [req-045](./Interface/req-045_kill-switch-execution.md) |
| REQ-046 | kill-switch 당일 제외 masking + 자동해제 + resume | Interface | Approved | High | project maintainers | [req-046](./Interface/req-046_killswitch-day-exclusion-masking-and-resume.md) |
| REQ-047 | kill-switch baseline 문서 정합 | Documentation | Approved | Medium | project maintainers | [req-047](./Documentation/req-047_killswitch-baseline-alignment.md) |
## Recent Change Log Summary
- 2026-06-07 :: REQ-043~047 Proposed → Approved (confirm-req): kill-switch 5개 전원 승인 게이트 통과. dcy-008(confirmed) 범위·결정(OQ-1/2/4 Answered, OQ-3 Deferred)과 모순 없음, 필수 필드·구체 AC·Impacted Area·Change Log 완비. 큐 rename 호환·전역 sentinel·pending_buy 는 비핵심 후속으로 blocker 아님. (confirm-req)
- 2026-06-07 :: REQ-043~047 생성 (draft-req): dcy-008(비상 정지/kill-switch, confirmed) → 5개 REQ 초안. 제어 채널 `trex.control.req`+action dispatch(043), day-scoped 제외 store+마이그레이션(044), kill-switch 실행=범위별 holding 순차 sell()+이력(045), 당일 제외 masking+자동복귀+resume_kill_switch(046), baseline 정합(047). NFR-1/2/3 은 045/046 AC 로 흡수, OQ-3(pending_buy) REQ Deferred. (draft-req)
- 2026-06-07 :: REQ-038 CHG-20260607-05 Approved → Implemented (confirm-req-implemented): tr_id 정정(`FHKST01010100`) 구현·재검증 — kis.py 수정, AC-7 테스트 정정, 단위 236 passed/ruff clean, 실 KIS LIVE `get_current_price=329000`(rt_cd=0) 확인.
- 2026-06-07 :: REQ-038 CHG-20260607-04 Implemented → Approved (change-req): 현재가 시세 tr_id 정정 `TTTC8397R`/`VTTC8397R` → `FHKST01010100`. 배포 전 실 KIS LIVE 진단에서 구 tr_id 가 "없는 서비스 코드"(rt_cd=1)로 거부 → LIVE 에서 손절/익절 silent 미발동 확인. 표준 시세 tr 정상(stck_prpr=329000). (change-req)
- 2026-06-07 :: REQ-037, REQ-038, REQ-039, REQ-040, REQ-042 Approved → Implemented (confirm-req-implemented): BAT-011 verify 완료(신규 38 테스트 green, 단위 236 passed, 인프라 게이트 259 passed, ruff clean). SafetySellService(forced_close/SL·TP KIS polling/장 마감), `BrokerPort.get_current_price`, `SlotService.update_thresholds` + intent RPC 액션, `trex-safety-sell` 7번째 스레드, baseline 3문서 정합 확인. (※ REQ-038 AC-7 tr_id 는 CHG-04 로 후속 정정)
- 2026-06-07 :: REQ-034, REQ-035, REQ-036, REQ-041 Approved → Implemented (confirm-req-implemented): BAT-010 verify 완료(32 신규 테스트 green, 95 회귀 passed). WatchdogStore, stop_loss/take_profit 도메인 필드, SQL 마이그레이션, SlotService.sell(), SafetySellConfig env vars 5종 구현 확인.
- 2026-06-07 :: REQ-034~042 Proposed → Approved (confirm-req): 9개 전원 승인 게이트 통과. dcy-007(confirmed) 범위·결정과 모순 없음, 필수 필드·AC·Impacted Area·Change Log 완비 확인. (confirm-req)