feat(execution): 체결가 0/None 시 지정가 백필 가드 + WARN 로깅 (dcy-032/BAT-048)

REQ-095(슬롯 평단·원장 price 지정가 백필, 0 오염 방지) + REQ-096(백필/미해결 WARN 로깅) 구현.
지정가 부재 시 skip+강WARN. application 단일화(_resolve_fill_price), wire/LedgerTrade 스키마 불변.
575 passed/0 fail, opus QC PASS. REQ-097 알람=스파이크 산출물만(impl 후속).

- _resolve_fill_price 헬퍼 추가: avg_price 검증, limit_price 백필, 미해결 WARN
- _on_filled/_on_partial_cancel 통합: 백필 적용, 슬롯/원장 일관성
- _record_ledger 시그니처: resolved_price 파라미터 (backward compat)
- test_execution_fill_price_backfill.py: 21 시나리오 (avg=None/0, limit=있음/없음 등)
- docs: dcy-032, req-095/096/097, bat-048 설계/검증

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
2026-06-21 13:34:31 +09:00
co-authored by Claude Opus 4.8
parent d182464b7a
commit f1b649cf2a
15 changed files with 2134 additions and 11 deletions
@@ -0,0 +1,74 @@
# req-097: 알람(alert) 능력 검토 스파이크 산출물
- Status: Approved
- Type: Documentation
- Priority: Medium
- Owner: trex-core-dev
## Intent
- trex-core에는 현재 구조화된 알람(alert) 채널이 없다. 운영자 표면은 CLI `trex-core report`와 구조화 로그가 전부이며, 이상 징후(체결가 백필 발생, price≤0 체결 등)를 운영자에게 즉시 푸시로 알리는 메커니즘이 부재한다.
- 본 REQ는 알람 능력 도입 여부와 최소 구현 범위를 결정하기 위한 스파이크(설계 분석) 산출물 작성을 요구한다. 실제 알람 구현 포함 여부는 이 산출물을 근거로 design review에서 사장님이 최종 결정한다.
- 본 REQ 자체는 "분석 산출물 제출"까지가 요구사항이며, 알람 구현은 설계 분석 결과에 따라 조건부로 포함 또는 후속 이월된다.
## Requirement
- trex-core-dev는 알람(alert) 채널 후보(아래 최소 3가지)에 대해 장단점·최소 구현 범위·M2 일정 적합성을 분석한 설계 스파이크 문서를 작성해야 한다.
- 후보 A: 구조화 로그 기반 (현재 Loki JSON 로그를 알람 소스로 활용 + 로그 기반 외부 알림 파이프라인)
- 후보 B: AMQP 이벤트 기반 (trex.events exchange 또는 신규 exchange에 알람 이벤트 발행 — wire 계약 영향 검토 필수)
- 후보 C: 외부 푸시 직접 연동 (Slack/webhook/등)
- 분석 산출물은 `docs/` 아래 별도 파일(또는 design 산출물 디렉토리)로 작성하며, design review 전에 팀장에게 제출되어야 한다.
- 알람 구현이 M2에 포함될 경우 최소 구현 범위(무엇을, 어디서, 어떤 채널로)를 명시해야 한다.
## Acceptance Criteria
1. Given draft-batch-design 단계, When trex-core-dev가 알람 스파이크 분석을 수행할 때, Then 후보 A·B·C(이상 3가지)에 대해 각각 장점·단점·최소 구현 범위·M2 일정 적합성을 명시한 문서가 작성된다.
2. Given 후보 B(AMQP 이벤트 기반) 분석, When 설계 문서가 작성될 때, Then wire 계약(slots RPC 스키마, trex.events 메시지 구조 등) 변경 여부와 blast radius(trex-orb-v1, trex-tsl-v1 영향)가 명시된다. wire 계약 변경이 수반되면 팀장에게 즉시 보고하고 멈춘다.
3. Given 분석 산출물이 팀장에게 제출된 후 design review, When 사장님이 알람 구현 범위를 결정할 때, Then "M2 포함" 또는 "후속 이월" 중 하나로 확정되어 REQ-097 Notes에 기록된다.
4. Given 알람 구현이 M2 포함으로 결정된 경우, When 신규 REQ가 생성될 때, Then 본 REQ에서 분석된 채널과 최소 범위를 근거로 구현 REQ가 별도 생성된다(본 REQ는 분석 산출물 REQ로 유지).
5. Given 알람 구현이 후속 이월로 결정된 경우, Then 본 REQ는 산출물 제출로 완료 처리되며, 구현 REQ는 별도 Discovery에서 정의한다.
## Impacted Area
- Docs:
- `docs/` 아래 신규 알람 스파이크 분석 파일 (design 단계 산출물, 경로 미확정)
- `docs/interface-contract.md` — 후보 B 채택 시 wire 계약 변경 필요 여부 검토 대상 (변경 시 별도 승인 필요)
- Modules: 없음 (본 REQ는 분석 산출물만 요구)
- Tests: 없음 (본 REQ는 문서 산출물; 구현 REQ 생성 시 해당 REQ에서 AC/테스트 정의)
## Notes
- **[사장님 결정 2026-06-21]** 스파이크 산출물(BAT-048 design.md 알람 섹션) 제출로 AC-1·AC-2 충족 → 본 REQ는 **산출물 완료**(AC-5 경로). **알람 구현은 BAT-048(백필+WARN 로깅) 완료 후 별도 후속 트랙으로 진행**하며, **M2 포함 여부도 그때 재결정**한다(현 시점 M2 미확정). design 권고: 후보 A(로그 기반)=WARN 로그+Loki 알람 룰, 후보 B(AMQP)=wire 계약 변경이라 제외, 후보 C(외부 푸시)=M3. BAT-048 구현 범위는 REQ-095+REQ-096만.
- **조건부 구현**: 본 REQ 완료(AC-1~2 충족, 분석 산출물 제출)는 알람 구현 REQ 생성의 선행 조건이다. 알람 구현 포함 여부(AC-3)는 사장님 결정 사안이며 design review 게이트에서 확정된다. trex-core-dev는 이 결정을 임의로 내리지 않는다.
- **wire 계약 변경 주의**: 후보 B(AMQP 이벤트) 분석 시 wire 계약 변경이 수반되면 trex-orb-v1·trex-tsl-v1에 파급 효과가 있다. 이 경우 즉시 팀장에게 보고하고 멈춘다(CLAUDE.md 교차 영향 사안 정책).
- FR-3 WARN 로깅(REQ-096)은 알람 채널 채택 여부와 무관하게 M2 필수 항목이며, 본 REQ와 독립적으로 진행된다.
- Discovery: dcy-032_20260621_fill-missing-price-cost-basis-backfill.md (FR-4, OQ-1)
## Change Log
### CHG-20260621-01
- Date: 2026-06-21
- Author: trex-core-dev
#### Change Summary
- 최초 생성 (draft-req dcy-032)
#### Intent
- 알람 능력 도입 여부를 결정하기 위한 스파이크 산출물 요구사항 신규 정의. 실제 구현 포함 여부는 design review 후 사장님 결정.
#### Acceptance Criteria Delta
- Added:
- AC-1~5 신규 정의
- Updated: 없음
- Removed: 없음
#### Impacted Area Delta
- Docs: docs/ 신규 스파이크 분석 파일, docs/interface-contract.md 검토 대상
- Modules: 없음
- Tests: 없음
#### Delivery Trace Delta
- Batches: 미정 (suggest-batch-reqs 이후 편성)
- Releases: 미정
#### Revalidation Impact
- Reverification Needed: no (최초 생성)
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: design review 후 AC-3 결과를 Notes에 반영 필요
@@ -0,0 +1,77 @@
# req-095: 체결가 0/None 지정가 백필 가드 (슬롯 평단 + 원장 price)
- Status: Approved
- Type: Exception
- Priority: High
- Owner: trex-core-dev
## Intent
- KIS 체결조회가 체결수량은 보고하면서 평균체결가(`avg`)를 None 또는 0으로 반환하는 순간 스냅샷이 발생할 수 있다. 현재 코드는 이 케이스를 무경고로 통과시켜 슬롯 평단(`slot.avg_price`)과 원장 cost basis(`_record_ledger` price)가 동시에 0으로 영구 오염된다. 완전체결 시 `clear_dispatch`로 재폴링이 없어 0이 영구화된다.
- 본 REQ는 체결(완전·부분) 처리에서 브로커 평균체결가가 None 또는 ≤0이면 주문 지정가(`limit_price`)로 백필해, 슬롯 평단과 원장 price가 0으로 저장되지 않도록 무결성 가드를 추가한다.
- 이 변경은 wire 계약(slots RPC 스키마) 변경 없이 값 정정만 수행하며, 정상 평균가 수신 경로(happy path)에 영향을 주지 않는다.
## Requirement
- 체결(완전 체결 및 부분 취소 후 체결) 처리 시, 브로커가 제공한 `fs.avg_price`가 None 또는 ≤0인 경우, 슬롯의 `avg_price` 계산(`_on_filled`, `_on_partial_cancel`)에 사용하는 `fill_price`를 주문 지정가(`slot.limit_price` 또는 동등한 주문 컨텍스트의 지정가)로 대체(백필)해야 한다.
- 동일 조건에서 `_record_ledger`의 `price` 결정도 동일한 백필 가격을 사용해야 하며, price=0인 원장 레코드가 생성되어서는 안 된다.
- 백필 결정 지점(adapter vs application)과 지정가마저 부재/≤0인 경우의 최종 폴백 정책은 design 단계에서 확정한다(아래 Notes 참조).
## Acceptance Criteria
1. Given `fs.avg_price`가 None인 체결 이벤트와 `slot.limit_price > 0`인 슬롯, When `_on_filled`의 평단 계산이 실행될 때, Then `fill_price`로 `slot.limit_price`가 사용되고 `slot.avg_price`에 지정가 기반 가중평균이 저장된다(0 저장 없음).
2. Given `fs.avg_price`가 0.0인 체결 이벤트와 `slot.limit_price > 0`인 슬롯, When `_on_partial_cancel`의 평단 계산이 실행될 때, Then `fill_price`로 `slot.limit_price`가 사용되고 `slot.avg_price`가 0이 아닌 값으로 저장된다.
3. Given `fs.avg_price`가 None인 체결 이벤트, When `_record_ledger`의 price 결정이 실행될 때, Then `LedgerWorkItem.price`로 0.0이 아닌 백필 지정가(≥0 초과)가 기록된다.
4. Given `fs.avg_price`가 정상 양수인 체결 이벤트(happy path), When `_on_filled`/`_on_partial_cancel`/`_record_ledger`가 실행될 때, Then 기존과 동일하게 `fs.avg_price`가 사용되며 백필 분기가 개입하지 않는다(회귀 없음).
5. Given wire 계약 관점(slots RPC 응답 스키마), When 백필이 발생할 때, Then RPC 메시지 구조·필드 집합이 변경되지 않는다(NFR-1: 값 정정만, 계약 불변).
6. Given `slot.limit_price`가 None 또는 ≤0인 극단 케이스(지정가마저 부재), When 백필 경로가 진입될 때, Then **체결 처리를 skip(슬롯 전이·원장 기록 미수행)하고 slot_id·symbol·broker_order_id·avg_price·limit_price·`reason=fill_price_unresolvable`를 포함한 강 WARN 로그를 발행한다**(0 저장 0건, 무경고 통과 0건). 슬롯은 PENDING 상태로 남아 watchdog/stale_pending 경보가 운영자 개입을 유도한다. [design BAT-048 KD-2 확정, 팀장 승인 2026-06-21]
## Impacted Area
- Docs: `docs/runtime-flows.md` — 체결 처리 흐름에 백필 분기 추가 필요 (implementation 후 갱신)
- Modules:
- `trex_core/application/execution.py` — `_on_filled`(`:242-251`), `_on_partial_cancel`(`:305-314`), `_record_ledger`(`:424`) 의 fill_price/price 결정 로직
- `trex_core/adapters/broker/kis.py` — `:209,219,232,238,243` 평균가 None/0 표면화 지점 (백필 결정을 adapter에서 할지 application에서 할지는 design 확정 대상)
- Tests:
- `tests/application/test_execution.py` (또는 동등 경로) — avg_price=None, avg_price=0, happy path 각각 단위 테스트
- `tests/integration/` — 체결→원장 기록 통합 경로 회귀 테스트
## Notes
- **design 확정 완료 (BAT-048 KD-1/KD-2, 팀장 승인 2026-06-21)**:
- 백필 결정 지점: **application 레이어 단일화** — `application/execution.py`에 `_resolve_fill_price` 헬퍼 신설. `BrokerPort.poll_fill`/adapter/paper 불변, dcy-021 reconcile 경로 자동 일관성(Discovery R-2 해소).
- 지정가마저 부재/≤0일 때 폴백: **skip + 강 WARN**(AC-6 반영). 재폴링은 완전체결 교착, 현재가 조회는 포트 계약 변경이라 기각(Discovery OQ-2 해소).
- AC-6 구체화 완료(위 design 확정 반영).
- NFR-2(happy path 무영향): AC-4로 흡수. NFR-3(백필 추적 가능): REQ-096 WARN 로깅으로 달성.
- Discovery 가정 A-1: orb 매수는 지정가 주문이므로 대다수 케이스에서 `slot.limit_price`가 존재한다.
- 원장 price=0 방지는 REQ-018(체결→원장 기록)의 무결성 연장이며, 원장 skip 가드(`portfolio_id` 부재, `execution_id` 부재)는 본 REQ와 독립적으로 유지된다.
- Discovery: dcy-032_20260621_fill-missing-price-cost-basis-backfill.md (FR-1, FR-2)
## Change Log
### CHG-20260621-01
- Date: 2026-06-21
- Author: trex-core-dev
#### Change Summary
- 최초 생성 (draft-req dcy-032)
#### Intent
- KIS 체결가 0/None 무경고 오염 방지를 위한 지정가 백필 가드 신규 요구사항 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~6 신규 정의
- Updated: 없음
- Removed: 없음
#### Impacted Area Delta
- Docs: docs/runtime-flows.md (implementation 후 갱신)
- Modules: trex_core/application/execution.py, trex_core/adapters/broker/kis.py
- Tests: tests/application/test_execution.py, tests/integration/
#### Delivery Trace Delta
- Batches: 미정 (suggest-batch-reqs 이후 편성)
- Releases: 미정
#### Revalidation Impact
- Reverification Needed: no (최초 생성)
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: design 확정 후 AC-6 구체화 필요
@@ -0,0 +1,70 @@
# req-096: 체결가 백필·0가격 통과 WARN 로깅
- Status: Approved
- Type: Exception
- Priority: High
- Owner: trex-core-dev
## Intent
- REQ-095의 백필 가드가 발동되거나, 백필 없이 price≤0 체결이 하류(원장·슬롯)로 통과하는 경우, 운영자가 사후에도 해당 이벤트를 식별할 수 있도록 구조화된 WARN 로그를 남겨야 한다.
- 현재 원장 skip 가드(`portfolio_id` 부재, `execution_id` 부재)는 각각 WARN을 남기는 반면, "체결됐는데 price≤0" 케이스는 어떤 가드에도 걸리지 않고 조용히 통과한다. 이 가시성 공백을 동일한 수준으로 맞춘다.
- WARN 로그는 슬롯·심볼·주문ID·원가격·대체가격·사유를 포함해 백필 항목이 실제 평균가인지 백필 근사인지 추적 가능(NFR-3)하게 한다.
## Requirement
- 체결(완전·부분 취소 후) 처리에서 REQ-095의 백필이 발동된 경우, 슬롯 ID·심볼·주문 ID·원 브로커 평균가(None 또는 0)·대체가격(백필 지정가)·사유(`avg_price_backfill`)를 포함한 WARN 수준 구조화 로그를 반드시 남겨야 한다.
- 지정가마저 부재/≤0인 극단 케이스(design 확정 폴백 정책 적용 시점)에서 백필이 불가능해 price≤0 상태가 하류로 넘어가는 경우에도, 동일한 필드 집합을 포함한 WARN(또는 그 이상 수준) 로그를 남겨야 한다.
- 정상 평균가(happy path) 수신 경로에서는 이 WARN 로그가 발생하지 않아야 한다.
## Acceptance Criteria
1. Given `fs.avg_price`가 None 또는 ≤0이고 지정가 백필이 적용된 체결, When 집행 루프가 해당 체결을 처리할 때, Then `slot_id`, `symbol`, `broker_order_id`(또는 동등 주문 식별자), 원 `avg_price`(None 또는 0), `backfill_price`(대체가), `reason=avg_price_backfill` 필드를 포함하는 WARN 로그가 정확히 1건 생성된다.
2. Given 지정가마저 부재/≤0인 극단 케이스(폴백 정책 적용), When 집행 루프가 해당 체결을 처리할 때, Then 슬롯·심볼·주문 ID·원가격·사유를 포함한 WARN 이상 수준 로그가 1건 이상 생성된다(0 저장 또는 skip 어느 쪽이든 무경고 통과 없음).
3. Given `fs.avg_price`가 정상 양수인 체결(happy path), When 집행 루프가 처리할 때, Then 백필 관련 WARN 로그가 생성되지 않는다.
4. Given 백필 WARN 로그가 생성된 후 운영자가 로그를 조회할 때, Then 해당 로그로부터 어떤 슬롯의 어떤 체결에서 백필이 발생했는지, 원래 브로커가 제공한 가격이 무엇이었는지, 어떤 가격으로 대체됐는지를 식별할 수 있다(NFR-3: 실제 평균가 vs 백필 근사 구분 가능).
## Impacted Area
- Docs: `docs/operations.md` — 백필 WARN 발생 시 운영자 점검 절차 추가 권고 (implementation 후 갱신)
- Modules:
- `trex_core/application/execution.py` — `_on_filled`, `_on_partial_cancel`, `_record_ledger` 내 백필 분기 후 WARN 로그 추가
- Tests:
- `tests/application/test_execution.py` (또는 동등 경로) — 백필 경로에서 WARN 로그 발생 단언, happy path에서 WARN 미발생 단언
## Notes
- 이 REQ는 REQ-095(백필 가드)와 독립적으로 측정 가능하다: REQ-095가 값 정정을, REQ-096이 가시성을 담당하며, 둘 다 같은 batch에서 구현해야 함께 의미가 있다.
- 원장 skip 가드(portfolio_id 부재 WARN, execution_id 부재 WARN)와 동일한 운영 가시성 수준을 목표로 한다(Discovery FR-3 기준).
- AC-2의 극단 케이스(지정가마저 부재)의 폴백 정책 세부 사항은 REQ-095와 동일하게 design 확정 대상이다. 본 REQ는 어떤 폴백 정책이 채택되더라도 무경고 통과가 없어야 한다는 원칙을 요구한다.
- NFR-3(백필 추적 가능) — Discovery NFR-3을 본 REQ AC-4로 흡수.
- Discovery: dcy-032_20260621_fill-missing-price-cost-basis-backfill.md (FR-3)
## Change Log
### CHG-20260621-01
- Date: 2026-06-21
- Author: trex-core-dev
#### Change Summary
- 최초 생성 (draft-req dcy-032)
#### Intent
- 백필 발생 및 price≤0 체결 통과 시 운영 가시성 확보를 위한 WARN 로깅 요구사항 신규 정의
#### Acceptance Criteria Delta
- Added:
- AC-1~4 신규 정의
- Updated: 없음
- Removed: 없음
#### Impacted Area Delta
- Docs: docs/operations.md (implementation 후 갱신)
- Modules: trex_core/application/execution.py
- Tests: tests/application/test_execution.py
#### Delivery Trace Delta
- Batches: 미정 (suggest-batch-reqs 이후 편성, REQ-095와 동일 batch 예상)
- Releases: 미정
#### Revalidation Impact
- Reverification Needed: no (최초 생성)
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: 없음
+8 -1
View File
@@ -74,7 +74,7 @@
## Next Requirement ID
- Current: `REQ-095`
- Current: `REQ-098`
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
## Requirement Register
@@ -175,9 +175,16 @@
| REQ-092 | 발행 전용 연결 idle keepalive (서버 측 heartbeat 사망 예방) | Exception | Implemented | High | project maintainers | [req-092](./Exception/req-092_publish-idle-keepalive.md) |
| REQ-093 | DLQ 가시성/경보 + emit 실패 경보 (trex.events.dlq 관측성) | Exception | Implemented | High | project maintainers | [req-093](./Exception/req-093_dlq-visibility-and-emit-error-alert.md) |
| REQ-094 | 이벤트 발행 신뢰성 baseline 문서 정합 (runtime-flows / project-structure / operations 갱신) | Documentation | Implemented | Medium | project maintainers | [req-094](./Documentation/req-094_event-publisher-reliability-baseline-alignment.md) |
| REQ-095 | 체결가 0/None 지정가 백필 가드 (슬롯 평단 + 원장 price) | Exception | Implemented | High | trex-core-dev | [req-095](./Exception/req-095_fill-price-zero-backfill-guard.md) |
| REQ-096 | 체결가 백필·0가격 통과 WARN 로깅 | Exception | Implemented | High | trex-core-dev | [req-096](./Exception/req-096_fill-price-backfill-warn-logging.md) |
| REQ-097 | 알람(alert) 능력 검토 스파이크 산출물 | Documentation | Implemented | Medium | trex-core-dev | [req-097](./Documentation/req-097_alert-capability-spike.md) |
## Recent Change Log Summary
- 2026-06-21 :: **BAT-048 confirm-batch-verification**(팀장): REQ-095·096 **Approved → Implemented**. 구현=`execution.py` `_resolve_fill_price` 단일화(application) + `_record_ledger` resolved_price + skip+강WARN. 검증=신규 21 단위 테스트(매수 16+매도 5), **전체 575 passed/47 skipped/0 fail**(팀장 독립 재실행) + ruff clean. 독립 opus QC=PASS-WITH-NOTES → NOTE-1(ruff 2건)·NOTE-2(매도 경로 테스트) 정정 완료. skip 경로 부분변이 없음·price=0 원장 미생성 QC 확인. wire/LedgerTrade 스키마 불변(AC-5). **통합 3건 미실행 결정**(영속/전송 어댑터 diff 0이라 타 서비스 DB migration/truncate 침습 회피, KIS avg=None은 sandbox 결정적 재현 불가, 실가동 시 REQ-096 WARN으로 탐지). REQ-097=스파이크 Implemented(알람 impl 후속). 다음=커밋(git-ops)→M2.
- 2026-06-21 :: **BAT-048 design review**(팀장+사장님): D-1 백필 지점=application 단일화·D-2 폴백=skip+강WARN **팀장 승인**(REQ-095 AC-6 구체화). **D-3 사장님 결정: 우선 백필+WARN 로깅(REQ-095/096)만 구현, 알람은 BAT-048 완료 후 별도 진행+M2 포함 여부 그때 결정**. REQ-097 스파이크 산출물(design.md) 제출로 **Implemented**(후보 A 권고/B=wire변경 제외/C=M3). BAT-048 구현 범위=REQ-095+096.
- 2026-06-21 :: REQ-095·096·097 **Proposed → Approved** (confirm-req, 팀장): 세 REQ가 dcy-032 FR-1~4·NFR-1~3을 충실히 반영, AC 측정 가능, design Deferred 항목(백필 지점·지정가 부재 폴백·알람 채널) 명시 확인. REQ-095 AC-6(지정가 부재 폴백)은 design 확정 후 구체화(사장님 합의 deferral). 다음=suggest-batch-reqs → draft-batch.
- 2026-06-21 :: REQ-095·096·097 신규 생성(Proposed, draft-req dcy-032): 체결가 무결성 가드 — REQ-095 체결가 0/None 지정가 백필(슬롯 평단+원장 price, FR-1/2, wire 계약 불변, design 확정 대상: 백필 지점/지정가 부재 폴백), REQ-096 WARN 로깅(FR-3, 원장 skip 가드 동일 수준, NFR-3 흡수), REQ-097 알람 능력 검토 스파이크 산출물(FR-4, 구현 포함 여부 design review 후 사장님 결정, 조건부). NFR-1(wire 불변) REQ-095 AC-5 흡수, NFR-2(happy path 무영향) REQ-095 AC-4 흡수, NFR-3(백필 추적) REQ-096 AC-4 흡수.
- 2026-06-19 :: REQ-091·092·093·094 Approved → **Implemented** (confirm-req-implemented, BAT-047 release-candidate, dcy-031/OPS-005): 발행 재시도+강제재연결(091)·idle keepalive(092, execution-loop 단일스레드 틱)·DLQ 가시성+emit ERROR 경보(093, 구조화 로그 dcy-029 재사용)·baseline 정합(094) 구현·검증 완료. 독립 opus QC=PASS-WITH-NOTES→시정 2건(ruff F401·AC-3 프로덕션 경로) 완료, 팀장 재확인 **554 passed/47 skipped/회귀 0/ruff clean**. NFR-1 wire 무회귀(interface-contract diff 0). 수용 한계: half-open/broker재시작/idle=mock unit만(실 broker 통합 skip→운영/CI 위임), NFR-2 ≤5초는 재연결+재시도 구간만 엄밀(1차 socket_timeout 5s 최악 초과 가능). OQ-1/3 design Answered. 다음=draft-release(배포=trex-core 재배포→사장님 결재, tsl 라이브 선행).
- 2026-06-19 :: REQ-091·092·093·094 Proposed → **Approved** (confirm-req, 팀장): 필수 필드·구체 AC 충족, source dcy-031(confirmed, Open OQ 0) 정합, blocker 없음. 팀장 판정 — FR-4의 REQ-093 흡수 동의, OQ-1/OQ-3 design 인계 확정, NFR-2 타임아웃 수치는 draft-batch-design 확정(비차단). 다음=suggest-batch-reqs + draft-batch(REQ-091~094 단일 batch 편성 예정, 고위험 opus QC).
- 2026-06-19 :: REQ-091·092·093·094 신규 생성(Proposed, draft-req dcy-031): 이벤트 발행 연결 신뢰성 — REQ-091 발행 재시도+강제 재연결(FR-1/B, S-1·S-2, NFR-1~3 흡수), REQ-092 idle keepalive(FR-2/A, OQ-1 design 인계), REQ-093 DLQ 가시성+emit 경보(FR-3/D + FR-4, OQ-3 design 인계, S-3), REQ-094 baseline 문서 정합(runtime-flows/project-structure/operations, docs전용). NFR-2·NFR-3은 REQ-091~093 AC에 흡수. 고위험(M1 라이브) batch — opus QC 강제(CONFIRM①).