docs(dcy-033): 제품군 알람 전달 체계 discovery + REQ-098~101 (trex-core 소유분)
confirm-discovery + draft-req + confirm-req 완료. 알람 envelope wire 계약(098)· trex.alerts AMQP exchange 가산·격리(099)·core CRITICAL emitter 8종 best-effort 비차단(100)·baseline 정합(101). 전송=trex.alerts AMQP 확정, paging=ALARM-INVENTORY §A 전체. delivery는 M2 이후 큐잉. orb/tsl/kdh emitter·trex-notifier는 각 repo 별도. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# req-101: 알람 발신 흐름 baseline 문서 정합
|
||||
|
||||
- Status: Approved
|
||||
- Type: Documentation
|
||||
- Priority: Medium
|
||||
- Owner: trex-core-dev
|
||||
|
||||
## Intent
|
||||
- dcy-033 요구에 따라 `docs/runtime-flows.md`에 trex-core 알람 발신 흐름을 추가하고, `docs/interface-contract.md`의 알람 채널 섹션(REQ-098/099)이 완성되도록 Change Log를 갱신해 baseline 정합을 완료한다.
|
||||
- REQ-098·099·100 구현으로 변경되는 아키텍처 흐름(알람 발행 경로)이 baseline 문서에 반영되지 않으면 향후 Discovery·batch design에서 오래된 문서를 참조하는 오류가 생긴다.
|
||||
|
||||
## Requirement
|
||||
- `docs/runtime-flows.md`에 `Flow: 알람 발신 (trex.alerts, dcy-033)` 섹션을 추가해야 한다. 섹션에는 다음 내용이 포함되어야 한다.
|
||||
- 알람 발생 → `AlarmEmitter.publish_alarm()` → `MessagingTransport.publish_alarm_event()` → `trex.alerts` exchange → routing key `alarm.{severity}.{source}` 흐름.
|
||||
- best-effort 비차단 정책: 발행 실패 시 ERROR 로그 후 core 본업 계속.
|
||||
- transport 미연결 시 silent skip.
|
||||
- trex-core CRITICAL code 8종 발생 지점 목록(코드 이름과 모듈 경로).
|
||||
- 기존 `trex.events` 발행 흐름과의 차이(알람 채널은 독립 exchange, mandatory=False, DLQ 없음).
|
||||
- `docs/interface-contract.md`의 Change Log에 dcy-033/REQ-098~101 배치로 인한 알람 채널 추가 항목을 기록해야 한다.
|
||||
- 두 문서의 `Last Updated (KST)` 헤더를 구현 batch 완료 시점으로 갱신해야 한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Given REQ-098·099·100이 구현 완료됐을 때, When `docs/runtime-flows.md`를 검토하면, Then `Flow: 알람 발신 (trex.alerts, dcy-033)` 또는 동등한 제목의 섹션이 존재해야 한다.
|
||||
2. Given 해당 섹션이 추가됐을 때, When 내용을 확인하면, Then AlarmEmitter → MessagingTransport → trex.alerts exchange의 발행 흐름과 best-effort 비차단 정책이 명시되어야 한다.
|
||||
3. Given 섹션이 추가됐을 때, When core CRITICAL code 목록을 확인하면, Then ALARM-INVENTORY §A core 행의 8개 code(`fill_price_unresolvable`, `sell_skipped_no_balance`, `core_holding_broker_flat`, `ledger_delivery_failed`, `kill_switch_fired`, `publish_unavailable_after_reconnect`/`dlq_publish_failed`, `portfolio_hub_unavailable`, `schema_verification_failed`/`migration_failed`)와 발생 모듈 경로가 모두 기술되어야 한다.
|
||||
4. Given 섹션이 추가됐을 때, When `trex.events` 발행 흐름과 비교하면, Then 알람 채널(`trex.alerts`)이 별도 exchange이고 `mandatory=False`·DLQ 없는 점이 명시되어야 한다(기존 흐름 섹션 내용은 변경 없음).
|
||||
5. Given REQ-098~101 구현이 완료됐을 때, When `docs/interface-contract.md`의 Change Log를 확인하면, Then dcy-033/알람 채널 추가에 해당하는 항목이 기록되어야 한다.
|
||||
6. Given 두 baseline 문서가 갱신됐을 때, When `Last Updated (KST)` 헤더를 확인하면, Then 구현 batch 완료 시점(KST)으로 갱신되어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
- `docs/runtime-flows.md` — 알람 발신 흐름 섹션 추가(기존 섹션 불변)
|
||||
- `docs/interface-contract.md` — Change Log 항목 추가, Last Updated 갱신
|
||||
- Modules: 코드 변경 없음(이 REQ는 문서 정합만)
|
||||
- Tests: 문서 전용 REQ이므로 코드 테스트 불필요. batch verification에서 섹션 존재·내용 수동 검토.
|
||||
|
||||
## Notes
|
||||
- 이 REQ는 REQ-098·099·100 구현이 완료된 동일 batch에서 함께 처리한다(문서는 구현 후 정합).
|
||||
- `docs/runtime-flows.md`의 기존 섹션(데몬 lifecycle, slots RPC, intent admission, 이벤트 발행/구독, safety-sell 등)은 변경하지 않는다.
|
||||
- dcy-033 FR-3(baseline 갱신) 대응.
|
||||
- dcy-033 성공기준 S-3(기존 wire 계약 무회귀) — 이 REQ 자체는 문서 전용이지만 기존 섹션 diff=0이 AC-4에서 암묵 검증된다.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260621-01
|
||||
- Date: 2026-06-21
|
||||
- Author: trex-core-dev
|
||||
|
||||
#### Change Summary
|
||||
- REQ-101 신규 생성(Proposed). dcy-033 FR-3 대응: 알람 발신 흐름 baseline 문서 정합.
|
||||
|
||||
#### Intent
|
||||
- REQ-098~100 구현으로 도입된 알람 발신 흐름을 runtime-flows.md와 interface-contract.md에 반영해 baseline을 최신 상태로 유지한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: AC-1~6 (신규 생성)
|
||||
- Updated: (없음)
|
||||
- Removed: (없음)
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- `docs/runtime-flows.md` 알람 발신 섹션 추가
|
||||
- `docs/interface-contract.md` Change Log + Last Updated 갱신
|
||||
- Modules: 없음
|
||||
- Tests: 없음(문서 전용)
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: (미정, M2 이후 큐잉 — REQ-098~100과 동일 batch)
|
||||
- Releases: (미정)
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: REQ-098~100 구현 batch에서 마지막 단계로 처리
|
||||
|
||||
#### Validation Plan
|
||||
- `docs/runtime-flows.md`에 알람 발신 섹션 존재 확인(grep)
|
||||
- 섹션 내용 수동 검토(AlarmEmitter 흐름, 8 code 목록, mandatory=False, DLQ 없음)
|
||||
- `docs/interface-contract.md` Change Log 항목 추가 확인
|
||||
- 기존 섹션 diff=0 확인(git diff 수동 검토)
|
||||
@@ -0,0 +1,87 @@
|
||||
# req-099: trex.alerts AMQP exchange 토폴로지 + 가산·격리 불변식
|
||||
|
||||
- Status: Approved
|
||||
- Type: Integration
|
||||
- Priority: High
|
||||
- Owner: trex-core-dev
|
||||
|
||||
## Intent
|
||||
- 알람 전달 채널로 전용 `trex.alerts` topic exchange를 선언하고, 토폴로지(exchange 타입·이름·라우팅 규약)와 소비자/발행자 역할을 `docs/interface-contract.md`에 명시한다.
|
||||
- 이 채널은 **가산·격리** 원칙을 따른다: 기존 exchange/큐(trex.events/trex.intent.req/trex.slots.req/trex.control.req 등) 스키마와 동작은 일절 변경하지 않으며, `trex.alerts`는 독립 추가 채널로만 존재한다.
|
||||
- trex-core 데몬이 기동 시 `trex.alerts` exchange를 멱등 선언(declare)하도록 `MessagingTransport.declare_topology()`를 확장한다.
|
||||
|
||||
## Requirement
|
||||
- trex-core `MessagingTransport.declare_topology()`는 아래 AMQP 엔티티를 멱등으로 선언해야 한다.
|
||||
- exchange: `trex.alerts`, type=`topic`, durable=`True`
|
||||
- 모듈(trex-core/orb/tsl/kdh)은 기존 RabbitMQ 연결에서 `trex.alerts` exchange로 알람 envelope를 발행한다. routing key는 `alarm.{severity}.{source}` (예: `alarm.critical.trex-core`).
|
||||
- trex-notifier는 `trex.alerts` exchange의 단일 소비자로서, 바인딩 패턴 `alarm.#`(또는 severity별 `alarm.critical.#`)으로 자신의 큐를 바인딩해 수신한다(notifier 큐 선언·바인딩은 trex-notifier 소유).
|
||||
- trex-core가 알람을 발행(publish)할 때: `mandatory=False`(소비자 없어도 unroutable 에러 없이 조용히 drop) — notifier 다운이 core 발행을 막지 않도록 한다.
|
||||
- 기존 AMQP 토폴로지(trex.events topic exchange, trex.events.dlq, trex.intent.req/trex.slots.req/trex.control.req 큐, trex.direct/trex.broadcast exchange)는 수정하지 않는다.
|
||||
- `docs/interface-contract.md`의 알람 채널 섹션(REQ-098)에 exchange 타입·이름·라우팅 규약·발행자/소비자 역할을 명시한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Given trex-core 데몬이 기동될 때, When `declare_topology()`가 호출되면, Then `trex.alerts`(topic, durable=True) exchange가 멱등 선언되어야 한다(이미 존재하면 no-op).
|
||||
2. Given `trex.alerts` exchange가 선언됐을 때, When 기존 exchange/큐 목록(trex.events, trex.events.dlq, trex.intent.req, trex.slots.req, trex.control.req, trex.direct, trex.broadcast)을 확인하면, Then 이들 엔티티의 type·durable·인수(arguments)가 변경되지 않아야 한다.
|
||||
3. Given trex-core가 알람을 발행할 때, When notifier 큐가 바인딩되지 않아 unroutable인 경우, Then `mandatory=False`이므로 발행이 조용히 성공하고(silent drop) TransportUnavailableError 또는 UnroutableError가 발생하지 않아야 한다.
|
||||
4. Given `docs/interface-contract.md` 알람 채널 섹션(REQ-098)이 추가됐을 때, When 토폴로지 명세를 확인하면, Then exchange 이름(`trex.alerts`), 타입(`topic`), durable 여부, routing key 형식(`alarm.{severity}.{source}`), 발행자(모든 모듈), 단일 소비자(trex-notifier)가 명시되어야 한다.
|
||||
5. Given `declare_topology()`가 `trex.alerts` exchange를 포함하도록 수정됐을 때, When 기존 topology 선언 관련 단위 테스트를 실행하면, Then 기존 테스트가 모두 통과하고 신규 exchange 선언에 대한 단위 테스트가 추가되어야 한다.
|
||||
6. Given trex-core가 알람을 발행할 때, When publishing 시 transport가 `disconnected` 또는 `reconnecting` 상태이면, Then 알람 발행은 silently skip되어야 하며 core 본업(슬롯 전이·매매 집행)을 블로킹하지 않아야 한다(best-effort 비차단 — REQ-100 연계).
|
||||
|
||||
## Impacted Area
|
||||
- Docs: `docs/interface-contract.md` — 알람 채널 섹션 토폴로지 내용 추가(REQ-098 섹션 확장)
|
||||
- Modules:
|
||||
- `trex_core/adapters/broker/rabbitmq.py` 또는 topology 선언 담당 모듈 — `trex.alerts` exchange 선언 추가
|
||||
- `trex_core/application/` messaging 관련 모듈 — 알람 발행 헬퍼(REQ-100 연계)
|
||||
- Tests:
|
||||
- `tests/adapters/` 또는 `tests/application/` — `declare_topology` 단위 테스트에 `trex.alerts` exchange 선언 assertion 추가
|
||||
- 기존 topology 선언 테스트 회귀 확인
|
||||
|
||||
## Notes
|
||||
- `trex.alerts` exchange는 `trex.events`와 별개로 선언된다. 둘은 다른 exchange 이름을 가지므로 바인딩·라우팅이 교차하지 않는다.
|
||||
- notifier가 없는 환경(개발/테스트)에서도 core는 정상 동작해야 한다. `mandatory=False` + best-effort 발행이 이를 보장한다.
|
||||
- RabbitMQ topology attribute 충돌(기존 큐·exchange와 durable/type 불일치) 시 PRECONDITION_FAILED — 이는 기존 엔티티 수정 금지 불변식을 위반한 경우로, 이 REQ의 AC-2로 사전 방지된다.
|
||||
- orb/tsl/kdh는 자신의 RabbitMQ 연결에서 `trex.alerts` exchange로 직접 발행한다. core는 이들의 연결을 관여하지 않는다(각 모듈 REQ 범위).
|
||||
- trex-notifier의 큐 이름·바인딩 패턴·prefetch 등은 trex-notifier repo REQ에서 정의한다.
|
||||
- dcy-033 NFR-1(가산·격리) 대응 — AC-2가 직접 검증 기준.
|
||||
- dcy-033 성공기준 S-3(기존 wire 계약 무회귀) 연계.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260621-01
|
||||
- Date: 2026-06-21
|
||||
- Author: trex-core-dev
|
||||
|
||||
#### Change Summary
|
||||
- REQ-099 신규 생성(Proposed). dcy-033 FR-2 대응: `trex.alerts` AMQP exchange 토폴로지 + 가산·격리 불변식.
|
||||
|
||||
#### Intent
|
||||
- `trex.alerts` 전용 exchange를 선언하고, 기존 AMQP 계약을 건드리지 않으면서 알람 채널을 가산적으로 추가한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: AC-1~6 (신규 생성)
|
||||
- Updated: (없음)
|
||||
- Removed: (없음)
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- `docs/interface-contract.md` 알람 채널 섹션(REQ-098)에 토폴로지 내용 추가
|
||||
- Modules:
|
||||
- topology 선언 담당 모듈에 `trex.alerts` exchange 추가
|
||||
- Tests:
|
||||
- topology 선언 단위 테스트 신규 assertion 추가
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: (미정, M2 이후 큐잉)
|
||||
- Releases: (미정)
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: REQ-098/100/101과 단일 batch 편성 예정
|
||||
|
||||
#### Validation Plan
|
||||
- RabbitMQ mock/stub에서 `declare_topology()` 호출 후 `trex.alerts` exchange 선언 assertion
|
||||
- 기존 exchange/큐 선언 테스트 회귀 통과 확인
|
||||
- `mandatory=False` 발행 시 unroutable 상황에서 예외 없음 확인(단위 테스트)
|
||||
@@ -0,0 +1,108 @@
|
||||
# req-100: trex-core 알람 emitter — CRITICAL code 발신 배선
|
||||
|
||||
- Status: Approved
|
||||
- Type: Integration
|
||||
- Priority: High
|
||||
- Owner: trex-core-dev
|
||||
|
||||
## Intent
|
||||
- ALARM-INVENTORY.md §A trex-core 행의 CRITICAL alarm code 8종을 trex-core 소스 내 발생 지점에서 REQ-098 envelope 형식으로 `trex.alerts` exchange(REQ-099)에 발행하도록 배선한다.
|
||||
- 알람 발행은 **best-effort 비차단**: 발행 실패(transport 단절·예외)가 core 본업(슬롯 전이·매매 집행·원장 기록)을 막지 않아야 한다.
|
||||
- trex-core는 텔레그램 토큰 등 외부 시크릿을 보유하지 않는다. core는 `trex.alerts` exchange에 발행만 하고, 텔레그램 전달은 trex-notifier 책임이다.
|
||||
|
||||
## Requirement
|
||||
- trex-core는 아래 8개 CRITICAL code의 발생 지점에서 REQ-098 envelope을 `trex.alerts` exchange로 발행해야 한다.
|
||||
|
||||
| code | 발생 위치 (ALARM-INVENTORY §A 기준) | 조건 |
|
||||
|---|---|---|
|
||||
| `fill_price_unresolvable` | `execution.py:261` | 체결가 미해결 → 슬롯 PENDING 고착 |
|
||||
| `sell_skipped_no_balance` | `execution.py:128` | 매도 dispatch skip (브로커 잔고 0) → PENDING_SELL 고착 |
|
||||
| `core_holding_broker_flat` | `reconciliation.py:47` | 슬롯 보유인데 브로커 잔고 0 (정산 불일치) |
|
||||
| `ledger_delivery_failed` | `ledger_outbox.py:218-245` | 원장 영구 실패/데드레터/409 충돌 |
|
||||
| `kill_switch_fired` | `killswitch.py:72` | 긴급 청산 발동 |
|
||||
| `publish_unavailable_after_reconnect` / `dlq_publish_failed` | `rabbitmq.py:262,293` | 재연결 후에도 발행 불가 / DLQ 발행 실패 |
|
||||
| `portfolio_hub_unavailable` | `portfolio.py:156` / `snapshot_scheduler.py:90,98` | 포트폴리오/현금 정보 부실화 |
|
||||
| `schema_verification_failed` / `migration_failed` | `reset.py:152` | 리셋·마이그레이션 무결성 실패 |
|
||||
|
||||
- 알람 emitter는 application 레이어에 `AlarmEmitter` (또는 동등한 이름의 thin class/함수)로 구현하며, `MessagingTransport` 포트를 통해 발행한다(직접 pika 호출 금지 — 의존성 역전 유지).
|
||||
- 발행 실패(TransportUnavailableError 또는 기타 예외) 시 ERROR 로그를 남기고 예외를 삼킨다(re-raise 금지). 슬롯 전이·주문 집행·원장 기록 경로는 알람 발행 실패에 영향받지 않는다.
|
||||
- envelope `source` = `"trex-core"`, `severity` = `"critical"`, `schema_version` = `"1"`. `occurred_at`은 발행 시점 KST ISO-8601.
|
||||
- `fields`는 code별 최소 컨텍스트를 포함한다(예: `fill_price_unresolvable`이면 `{"slot_id": "...", "symbol": "..."}`). 빈 dict도 허용.
|
||||
- trex-core 코드 어디에도 텔레그램 봇 토큰, chat_id 등 외부 알람 시크릿을 import·로드·참조하지 않는다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Given trex-core가 기동돼 `MessagingTransport`가 연결된 상태에서, When 위 8개 code 각각의 조건이 발생하면, Then 해당 code를 담은 REQ-098 envelope(`source="trex-core"`, `severity="critical"`, `schema_version="1"`)이 routing key `alarm.critical.trex-core`로 `trex.alerts` exchange에 발행되어야 한다.
|
||||
2. Given 알람 emitter가 `publish_alarm()`을 호출할 때, When `MessagingTransport`가 `disconnected` 또는 `reconnecting` 상태(TransportUnavailableError 발생)이면, Then 예외가 caller로 전파되지 않고 ERROR 로그만 남겨야 한다.
|
||||
3. Given 알람 emitter가 `publish_alarm()`을 호출할 때, When 발행 중 임의 예외가 발생하면, Then 예외가 caller로 전파되지 않고 ERROR 로그만 남겨야 한다.
|
||||
4. Given `kill_switch_fired`·`ledger_delivery_failed`·`fill_price_unresolvable` 등 알람 발행 지점이 슬롯 전이·매매 집행·원장 기록 경로 중간에 위치할 때, When 알람 발행이 예외로 실패해도, Then 해당 경로(슬롯 전이·집행·원장 기록)는 정상 완료되거나 기존 에러 처리 흐름을 따라야 한다(알람 발행 실패가 core 본업 실패를 유발하지 않음).
|
||||
5. Given trex-core 코드베이스 전체를 탐색할 때, When 텔레그램 봇 토큰·chat_id·TELEGRAM_* 환경변수를 참조하는 코드를 찾으면, Then 해당 참조가 0건이어야 한다.
|
||||
6. Given 알람 emitter 구현이 완료됐을 때, When `AlarmEmitter`(또는 동등 컴포넌트)의 단위 테스트를 실행하면, Then 8개 code 각각에 대해 (a) 정상 발행 시 올바른 envelope 필드 검증, (b) transport 예외 발생 시 re-raise 없음 + 로그 기록 두 케이스가 모두 통과해야 한다.
|
||||
7. Given `AlarmEmitter`가 `MessagingTransport` 포트를 통해 구현됐을 때, When application 레이어 코드를 확인하면, Then pika 라이브러리를 직접 import하는 코드가 없어야 한다(의존성 역전 준수).
|
||||
8. Given domain 레이어(`trex_core/domain/`) 코드를 확인할 때, When `AlarmEmitter` 또는 messaging import를 탐색하면, Then domain 레이어에 messaging/transport/infra 관련 import가 없어야 한다(domain 순수성 불변식).
|
||||
|
||||
## Impacted Area
|
||||
- Docs: `docs/interface-contract.md` — 알람 채널 섹션에 core emitter source/routing key 명시(REQ-098 섹션 내용)
|
||||
- Modules:
|
||||
- `trex_core/application/` — `AlarmEmitter` (또는 동등 thin class/함수) 신규 추가
|
||||
- `trex_core/application/execution.py` — `fill_price_unresolvable`, `sell_skipped_no_balance` 발행 배선
|
||||
- `trex_core/application/reconciliation.py` — `core_holding_broker_flat` 발행 배선
|
||||
- `trex_core/application/ledger_outbox.py` — `ledger_delivery_failed` 발행 배선
|
||||
- `trex_core/application/killswitch.py` — `kill_switch_fired` 발행 배선
|
||||
- `trex_core/adapters/broker/rabbitmq.py` — `publish_unavailable_after_reconnect` / `dlq_publish_failed` 발행 배선
|
||||
- `trex_core/adapters/portfolio/` 또는 `trex_core/application/snapshot_scheduler.py` — `portfolio_hub_unavailable` 발행 배선
|
||||
- `trex_core/runtime/reset.py` — `schema_verification_failed` / `migration_failed` 발행 배선
|
||||
- `trex_core/runtime/daemon.py` — `AlarmEmitter` 인스턴스 생성·주입
|
||||
- Tests:
|
||||
- `tests/application/` — `AlarmEmitter` 단위 테스트 (8 code × 2 케이스 최소 16 테스트)
|
||||
- 기존 execution/reconciliation/killswitch/ledger_outbox 테스트 회귀 확인
|
||||
|
||||
## Notes
|
||||
- `AlarmEmitter`는 application 레이어에 두고 `MessagingTransport` 포트만 주입받는다. 테스트에서는 `InMemoryTransport` 또는 mock transport를 주입해 결정적 단위 테스트를 작성한다.
|
||||
- `publish_unavailable_after_reconnect` / `dlq_publish_failed`는 rabbitmq.py 어댑터에서 발생하지만, 알람 emitter를 어댑터 내부에 두면 의존성이 역전되므로 처리 방식을 batch design에서 결정한다(예: 어댑터가 콜백을 호출하거나, 이벤트를 상위 레이어로 전달하는 방식).
|
||||
- `portfolio_hub_unavailable`는 `portfolio.py:156`과 `snapshot_scheduler.py:90,98` 두 곳에서 발생 가능 — 중복 발행 억제는 notifier의 rate-limit 책임이므로 core는 각 발생 지점에서 독립 발행한다.
|
||||
- `reset.py`는 daemon이 아닌 CLI 진입점(`trex-core-reset`)에서 실행된다. `MessagingTransport` 미연결 가능성 있음 — transport가 None이면 발행 skip + 로그(batch design에서 확정).
|
||||
- dcy-033 성공기준 S-1(CRITICAL 조건 발생 시 텔레그램 도달) 전제 조건: core emitter가 올바른 envelope을 `trex.alerts`에 발행.
|
||||
- dcy-033 NFR-3(core에 외부 시크릿 유입 없음) 대응 — AC-5가 직접 검증 기준.
|
||||
- INFO·WARN code 배선은 이 REQ 범위 밖. CRITICAL 우선(dcy-033 범위 경계).
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260621-01
|
||||
- Date: 2026-06-21
|
||||
- Author: trex-core-dev
|
||||
|
||||
#### Change Summary
|
||||
- REQ-100 신규 생성(Proposed). dcy-033 FR-2(core 부분) 대응: ALARM-INVENTORY §A core CRITICAL 8종 emitter 배선.
|
||||
|
||||
#### Intent
|
||||
- trex-core가 소유한 CRITICAL alarm code 발생 지점에서 표준 envelope을 `trex.alerts` exchange로 발행하는 알람 emitter를 구현한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: AC-1~8 (신규 생성)
|
||||
- Updated: (없음)
|
||||
- Removed: (없음)
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- `docs/interface-contract.md` 알람 섹션 core emitter 내용 추가
|
||||
- Modules:
|
||||
- application 레이어 AlarmEmitter 신규 + 8개 발생 지점 배선
|
||||
- Tests:
|
||||
- AlarmEmitter 단위 테스트 신규 추가
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: (미정, M2 이후 큐잉)
|
||||
- Releases: (미정)
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: REQ-098/099/101과 단일 batch 편성 예정
|
||||
|
||||
#### Validation Plan
|
||||
- AlarmEmitter 단위 테스트 8 code × 2 케이스 통과
|
||||
- 기존 execution/reconciliation/killswitch 테스트 회귀 통과
|
||||
- domain 레이어 messaging import 0건 확인(grep)
|
||||
- TELEGRAM_* 환경변수 참조 0건 확인(grep)
|
||||
@@ -0,0 +1,85 @@
|
||||
# req-098: 알람 envelope wire 계약 정의
|
||||
|
||||
- Status: Approved
|
||||
- Type: Interface
|
||||
- Priority: High
|
||||
- Owner: trex-core-dev
|
||||
|
||||
## Intent
|
||||
- 제품군 모든 모듈(core/orb/tsl/kdh)이 알람을 발신할 때 사용할 표준 메시지 envelope 스키마를 trex-core가 wire 계약으로 정의하고 `docs/interface-contract.md`에 명시한다.
|
||||
- 이 계약은 trex-notifier가 알람을 수집·분류할 때의 파싱 기준이 되며, 다른 모듈 repo(orb/tsl/kdh)와 trex-notifier가 이 문서를 단일 출처(source of truth)로 참조한다.
|
||||
- 기존 wire 계약(slots RPC/trex.events/trex.control.req)은 일절 변경하지 않는다.
|
||||
|
||||
## Requirement
|
||||
- trex-core는 알람 envelope의 표준 JSON 스키마를 아래 필드로 정의하고, `docs/interface-contract.md`에 신규 섹션 `Interface: trex.alerts (알람 채널, dcy-033)`으로 버전드 명시해야 한다.
|
||||
- `source` :: str — 알람 발신 모듈 식별자 (예: `"trex-core"`, `"trex-orb-v1"`, `"trex-tsl-v1"`, `"kis-data-hub"`)
|
||||
- `severity` :: `"critical"` | `"warn"` | `"info"` — 등급 (소문자 리터럴)
|
||||
- `code` :: str — 알람 식별 코드 (예: `"kill_switch_fired"`, `"fill_price_unresolvable"`)
|
||||
- `title` :: str — 사람이 읽는 1행 요약
|
||||
- `fields` :: dict[str, any] — 선택 구조화 컨텍스트 (예: `{"slot_id": "...", "symbol": "..."}`)
|
||||
- `occurred_at` :: ISO-8601 datetime string (UTC 또는 KST+09:00 offset 포함)
|
||||
- `schema_version` :: str — 현재 값 `"1"` (semver 주 버전 문자열; 소비자는 미인식 버전 무시·경고)
|
||||
- 계약 섹션에 routing key 규약(`alarm.{severity}.{source}`)과 exchange 이름(`trex.alerts`)을 함께 기술한다.
|
||||
- 이 스키마를 변경(필드 추가 포함)하면 `schema_version`을 올리거나 additive 변경 여부를 명시하도록 Update Trigger를 문서에 포함한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Given `docs/interface-contract.md`에 `Interface: trex.alerts (알람 채널, dcy-033)` 섹션이 존재하지 않을 때, When REQ-098 구현을 완료하면, Then 해당 섹션이 위 7개 필드(source/severity/code/title/fields/occurred_at/schema_version)의 JSON 스키마 명세를 포함해야 한다.
|
||||
2. Given 섹션이 추가됐을 때, When 명세를 검토하면, Then `severity` 값이 `"critical"` | `"warn"` | `"info"` 세 리터럴로 제한되고, `schema_version="1"`이 현재 버전으로 명시되어야 한다.
|
||||
3. Given 명세가 추가됐을 때, When 기존 interface-contract.md의 다른 섹션(slots RPC/trex.events/trex.control.req/strategy_state)을 검토하면, Then 기존 섹션의 내용이 변경되지 않아야 한다(가산·격리 불변 — diff는 신규 섹션 추가뿐).
|
||||
4. Given envelope 스키마 명세가 완성됐을 때, When routing key 규약을 확인하면, Then `alarm.{severity}.{source}` 형식이 명시되어야 한다.
|
||||
5. Given 명세가 추가됐을 때, When Update Trigger를 확인하면, Then 알람 envelope 스키마 변경(breaking/additive 모두) 시 이 문서를 갱신해야 한다는 트리거가 포함되어야 한다.
|
||||
6. Given 다른 모듈 repo(orb/tsl/kdh) 개발자가 알람 emitter를 구현할 때, When `docs/interface-contract.md`의 알람 계약 섹션을 읽으면, Then 자체 `trex_core` import 없이 envelope 구성에 필요한 모든 정보(필드·타입·필수 여부·schema_version·routing key)를 얻을 수 있어야 한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs: `docs/interface-contract.md` — 알람 채널 신규 섹션 추가(기존 섹션 불변)
|
||||
- Modules: 코드 변경 없음(이 REQ는 문서 계약만; emitter 구현은 REQ-100)
|
||||
- Tests: `docs/interface-contract.md` diff가 기존 섹션 변경 0임을 확인하는 검증(batch verification 단계에서 수동 검토 또는 diff assertion)
|
||||
|
||||
## Notes
|
||||
- 이 REQ는 **계약 문서화**만 담당한다. envelope을 실제로 직렬화·발행하는 Python 코드(알람 emitter)는 REQ-100이 담당한다.
|
||||
- `fields` 값은 opaque dict — core/notifier 모두 내용을 강제 파싱하지 않는다. 각 code별 권장 fields는 ALARM-INVENTORY.md를 참조한다.
|
||||
- `occurred_at` 형식: 권장은 KST+09:00 offset-aware ISO-8601(기존 코어 로깅 관례와 통일). UTC도 수용.
|
||||
- 다른 모듈(orb/tsl/kdh)은 `trex_core`를 import하지 않는다. 이 계약은 **문서 규약**이며 런타임 공유 코드가 아니다(Discovery 제약 A-1).
|
||||
- trex-notifier가 `schema_version`이 미인식인 envelope을 수신하면 경고 로그 후 무시한다(소비자 책임 — notifier REQ 범위).
|
||||
- dcy-033 성공기준 S-1(CRITICAL 알람 텔레그램 도달)·S-3(wire 계약 무회귀)의 선행 계약.
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260621-01
|
||||
- Date: 2026-06-21
|
||||
- Author: trex-core-dev
|
||||
|
||||
#### Change Summary
|
||||
- REQ-098 신규 생성(Proposed). dcy-033 FR-1 대응: 알람 envelope wire 계약 문서화.
|
||||
|
||||
#### Intent
|
||||
- dcy-033(제품군 알람 전달 체계) confirmed Discovery에서 요구하는 표준 알람 envelope 스키마를 trex-core wire 계약으로 정식화한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: AC-1~6 (신규 생성)
|
||||
- Updated: (없음)
|
||||
- Removed: (없음)
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs:
|
||||
- `docs/interface-contract.md` 신규 섹션 추가
|
||||
- Modules:
|
||||
- 코드 변경 없음
|
||||
- Tests:
|
||||
- interface-contract diff 검증(기존 섹션 불변 확인)
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: (미정, M2 이후 큐잉)
|
||||
- Releases: (미정)
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: confirm-req 후 batch 편성 시 REQ-099/100/101과 묶어 단일 batch로 처리 예정
|
||||
|
||||
#### Validation Plan
|
||||
- `docs/interface-contract.md`에 알람 채널 섹션이 추가됐는지 수동 확인
|
||||
- 기존 섹션 diff=0 확인(grep 또는 수동 비교)
|
||||
- 7개 필드·severity 리터럴·schema_version·routing key 규약이 모두 명시됐는지 체크리스트 검토
|
||||
+7
-1
@@ -74,7 +74,7 @@
|
||||
|
||||
## Next Requirement ID
|
||||
|
||||
- Current: `REQ-098`
|
||||
- Current: `REQ-102`
|
||||
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
|
||||
|
||||
## Requirement Register
|
||||
@@ -178,9 +178,15 @@
|
||||
| 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) |
|
||||
| REQ-098 | 알람 envelope wire 계약 정의 | Interface | Approved | High | trex-core-dev | [req-098](./Interface/req-098_alarm-envelope-wire-contract.md) |
|
||||
| REQ-099 | trex.alerts AMQP exchange 토폴로지 + 가산·격리 불변식 | Integration | Approved | High | trex-core-dev | [req-099](./Integration/req-099_alarm-exchange-topology.md) |
|
||||
| REQ-100 | trex-core 알람 emitter — CRITICAL code 발신 배선 | Integration | Approved | High | trex-core-dev | [req-100](./Integration/req-100_core-alarm-emitter.md) |
|
||||
| REQ-101 | 알람 발신 흐름 baseline 문서 정합 | Documentation | Approved | Medium | trex-core-dev | [req-101](./Documentation/req-101_alarm-baseline-alignment.md) |
|
||||
|
||||
## Recent Change Log Summary
|
||||
|
||||
- 2026-06-21 :: REQ-098·099·100·101 **Proposed → Approved** (confirm-req, 팀장): dcy-033 확정 설계(trex.alerts AMQP·envelope 7필드·core CRITICAL 8종) 충실 반영, AC 측정가능, 가산·격리 불변식(098 AC-3/099 AC-2)·best-effort 비차단(099 AC-6/100 AC-2~4)·시크릿 격리(100 AC-5)·의존성역전/domain 순수성(100 AC-7/8) 강제 확인. emitter-in-adapter 경계·reset.py transport는 batch design 확정. 다음=suggest-batch-reqs→draft-batch. **delivery는 첫 tsl REL(M2) 이후 큐잉.**
|
||||
- 2026-06-21 :: REQ-098·099·100·101 신규 생성(Proposed, draft-req dcy-033): 제품군 알람 전달 체계 — trex-core 소유분. REQ-098 알람 envelope wire 계약 정의(Interface, FR-1, dcy-033 S-1/S-3), REQ-099 trex.alerts AMQP exchange 토폴로지+가산·격리 불변식(Integration, NFR-1/S-3), REQ-100 core CRITICAL emitter 8종 배선(Integration, FR-2 core 부분, NFR-2/3, S-1), REQ-101 알람 발신 흐름 baseline 정합(Documentation, FR-3). orb/tsl/kdh emitter·trex-notifier는 각 repo REQ로 별도 진행. delivery는 M2 이후 큐잉.
|
||||
- 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.
|
||||
|
||||
Reference in New Issue
Block a user