feat(safety-sell): dcy-017 워치독 소유권 가시화 — snapshot 상태 + 발동 로깅 (BAT-021)
전략 이탈로 슬롯이 내부 청산 루틴(워치독) 소유로 넘어간 상태가 무성이라 운영자가 인지할 수 없던 문제(issue #12)를 가시화한다. 거버넌스: 전부 change-req (신규 REQ 없음, dcy-017 OQ-3; Redis 미채택). - REQ-034/021: WatchdogStore.last_seen + snapshot RPC 응답에 holding 슬롯 워치독 상태(expired/last_seen) read-only 동봉(best-effort) - REQ-032: trex-core slots 가 expired 슬롯을 WATCHDOG-OWNED(전략 이탈) 표시 - REQ-037/038/039: safety-sell 워치독 소유 진입(WARN)/이탈(INFO) + 발동 (forced_close·stop_loss=WARN, take_profit·market_close=INFO) 로그 + in-process 카운터(SafetySellService.counters), 구조화 필드(slot_id/ portfolio_id/reason/phase/instance_key). per-tick 스킵은 카운터만 - REQ-042: runtime-flows/interface-contract 정합 best-effort 격리(NFR-1): 모든 가시화는 예외 격리 — 워치독 판정·청산 불변. dcy-016 억제 읽기로 관측이 워치독을 리셋하지 않음(비침습). 검증: 단위 335 passed/34 skipped, 인프라 게이트(PG+RabbitMQ) 369 passed, ruff clean. 신규 test_safety_sell_visibility(6) + snapshot watchdog(1) + CLI(1). BAT-021 rc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# BAT-021 Design
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-021
|
||||
|
||||
## 설계 목표
|
||||
- 전략 이탈로 슬롯이 워치독(안전망) 소유로 넘어간 상태와 safety-sell 발동을 무성에서 가시화한다(issue #12). 가시화는 best-effort — 판정·청산을 절대 막지 않는다(NFR-1).
|
||||
|
||||
## 1. 워치독 상태 노출 (REQ-034/021)
|
||||
- `WatchdogStore.last_seen(slot_id) -> Optional[datetime]` read-only getter 추가(판정 로직 불변).
|
||||
- `make_snapshot_rpc_handler(..., watchdog_timeout_sec=120)` + `_attach_watchdog(payload, slot_repo, day, watchdog_store, timeout)`:
|
||||
- holding 슬롯마다 `{slot_id, portfolio_id, symbol, expired(is_expired), last_seen}` 산출 → `payload["watchdog"]`.
|
||||
- try/except 로 감싸 실패 시 응답 불변(best-effort). envelope·stub 두 경로 모두 attach.
|
||||
- additive top-level 필드라 REQ-028 strict asset shape(no-price) 불변.
|
||||
|
||||
## 2. safety-sell 가시화 (REQ-037/038/039, OQ-2)
|
||||
- `SafetySellService(instance_key="default")` + `self._owned: set` + `self.counters: dict`.
|
||||
- `_log_fire(slot, reason)`: `_WARN_REASONS={forced_close_at, stop_loss}` → WARN, 그 외(take_profit, market_close_liquidation) → INFO. 구조화 필드(phase/slot_id/portfolio_id/reason/instance_key) + `counters["fire:{reason}"]++`. check_forced_close/check_prices/check_market_close 의 발동 지점에서 호출.
|
||||
- `_update_ownership(now)`: grace 중이면 skip. `current = {holding ∧ watchdog_expired}`; `current - _owned` → WARN(owned:enter), `_owned - current` → INFO(owned:exit); `_owned = current`. run_once 매 tick 호출. 예외 격리.
|
||||
- per-tick 스킵/no-fire 평가는 로그 X, 카운터만(30초 로그 스팸 방지). 영속 거부 반복 경고는 REQ-052 별도.
|
||||
|
||||
## 3. CLI 표시 (REQ-032)
|
||||
- `_cmd_slots`: snapshot 응답의 `watchdog` 필드에서 `expired=true` 인 portfolio_id 집합 → 자산 출력에 `[WATCHDOG-OWNED: strategy absent]` 태그 + `watchdog_owned=N` 요약. `--json` 은 원응답 그대로.
|
||||
|
||||
## 4. 배선
|
||||
- daemon: snapshot handler 에 `watchdog_timeout_sec=config.safety_sell.watchdog_timeout_sec`; SafetySellService 에 `instance_key=config.instance_key`.
|
||||
|
||||
## 5. baseline 문서 (REQ-042)
|
||||
- runtime-flows: 워치독 갱신 flow 에 상태 노출(5) + `safety-sell 가시화` flow 신규(소유 진입/이탈·발동 차등·카운터·best-effort).
|
||||
- interface-contract: snapshot 응답 `watchdog[]` 필드.
|
||||
|
||||
## best-effort 격리 (NFR-1)
|
||||
- `_attach_watchdog`·`_update_ownership` 예외 무시(no-op), `_log_fire` 는 순수 로그/카운터. 워치독 판정(is_expired)·청산(`SlotService.sell`) source of truth 불변.
|
||||
|
||||
## 재시작 (R-3)
|
||||
- WatchdogStore·`_owned`·counters in-memory → 재시작 시 소유 상태 소실(폴링 재개 시 재구성). 발동 로그는 외부 로그 싱크에 이력 유지. 영속 승격은 Out of Scope.
|
||||
|
||||
## 테스트 설계
|
||||
- `tests/application/test_safety_sell_visibility.py`: 소유 진입 WARN+카운터, 이탈 INFO+카운터, 안정 시 churn 없음, forced_close WARN, take_profit INFO, grace 억제(6건). instance_key 로그 포함 단언.
|
||||
- `tests/application/test_messaging_snapshot_consumer.py`: 워치독 만료 holding → watchdog 필드 expired/last_seen 노출.
|
||||
- `tests/runtime/test_cli_operator.py`: slots 가 expired 슬롯을 WATCHDOG-OWNED 로 표시.
|
||||
@@ -0,0 +1,39 @@
|
||||
# BAT-021 Implementation
|
||||
|
||||
- Status: completed
|
||||
- Batch: BAT-021
|
||||
|
||||
## 구현 요약
|
||||
- dcy-017 워치독 소유권 가시화(snapshot 워치독 상태 + safety-sell 발동 로깅)를 전부 change-req 로 구현(신규 REQ 없음, Redis 미채택).
|
||||
|
||||
## 변경 내역
|
||||
|
||||
### REQ-034/021 — 워치독 상태 노출
|
||||
- `trex_core/application/watchdog.py`: `last_seen(slot_id) -> Optional[datetime]` read-only getter.
|
||||
- `trex_core/application/messaging_handlers.py`: `make_snapshot_rpc_handler(..., watchdog_timeout_sec=120)` + `_attach_watchdog(payload, ...)` — holding 슬롯 `{slot_id, portfolio_id, symbol, expired, last_seen}` 를 `payload["watchdog"]` 에 best-effort 동봉(envelope·stub 두 경로). try/except 격리.
|
||||
- `trex_core/runtime/daemon.py`: handler 에 `watchdog_timeout_sec=config.safety_sell.watchdog_timeout_sec` 배선.
|
||||
|
||||
### REQ-037/038/039 — safety-sell 발동·소유 가시화
|
||||
- `trex_core/application/safety_sell.py`:
|
||||
- `SafetySellService(instance_key="default")` + `self._owned: set` + `self.counters: dict` + `_count`.
|
||||
- `_log_fire(slot, reason)`: WARN(`forced_close_at`/`stop_loss`)·INFO(`take_profit`/`market_close_liquidation`) + `fire:{reason}` 카운터, 구조화 필드.
|
||||
- `_update_ownership(now)`: grace 밖에서 holding∧expired 집합 diff → 진입 WARN(`owned:enter`)/이탈 INFO(`owned:exit`). 예외 격리.
|
||||
- check_forced_close/check_prices/check_market_close 발동 지점에서 `_log_fire`; run_once 가 매 tick `_update_ownership`.
|
||||
- `trex_core/runtime/daemon.py`: SafetySellService 에 `instance_key=config.instance_key`.
|
||||
|
||||
### REQ-032 — CLI 표시
|
||||
- `trex_core/runtime/cli.py::_cmd_slots`: snapshot 응답 `watchdog` 에서 `expired` 슬롯 → `[WATCHDOG-OWNED: strategy absent]` 태그 + `watchdog_owned=N` 요약.
|
||||
|
||||
### REQ-042 — baseline 문서
|
||||
- `docs/runtime-flows.md`: 워치독 갱신 flow 에 상태 노출(5) + `safety-sell 가시화` flow 신규. Last Updated → BAT-021.
|
||||
- `docs/interface-contract.md`: snapshot 응답 `watchdog[]` 필드. Last Updated → BAT-021.
|
||||
|
||||
## 테스트
|
||||
- 신규 `tests/application/test_safety_sell_visibility.py`: 6건 — 소유 진입 WARN+카운터(instance_key 포함), 이탈 INFO+카운터, 안정 시 churn 없음, forced_close WARN, take_profit INFO, grace 억제.
|
||||
- `tests/application/test_messaging_snapshot_consumer.py` 확장: 워치독 만료 holding → watchdog 필드 expired/last_seen 노출(operator 비침습).
|
||||
- `tests/runtime/test_cli_operator.py` 확장: slots 가 expired 슬롯 WATCHDOG-OWNED 표시.
|
||||
|
||||
## 검증 실행
|
||||
- 단위: `TREX_BROKER=paper .venv/bin/python -m pytest -q` → `335 passed / 34 skipped`(`::test_sandbox_token_and_submit` deselect — LIVE `.env` 환경 의존, 본 batch 무관).
|
||||
- 인프라 게이트: `TREX_POSTGRESQL_TEST_DSN=...(trex_core_test) TREX_RABBITMQ_TEST_URL=... pytest -q` → `369 passed`.
|
||||
- `ruff check trex_core tests` → All checks passed.
|
||||
@@ -0,0 +1,34 @@
|
||||
# BAT-021: 워치독 소유권 가시화 — 스냅샷 워치독 상태 + safety-sell 발동 로깅 (dcy-017)
|
||||
|
||||
- Status: release-candidate
|
||||
- Profile: standard
|
||||
- Source Discovery: dcy-017
|
||||
- Included REQ: REQ-034 (CHG-20260608-02), REQ-021 (CHG-20260608-03), REQ-037 (CHG-20260608-01), REQ-038 (CHG-20260608-01), REQ-039 (CHG-20260608-01), REQ-032 (CHG-20260608-02), REQ-042 (CHG-20260608-01)
|
||||
|
||||
## Summary
|
||||
- dcy-017(전략 이탈로 슬롯이 내부 청산 루틴(워치독) 소유로 넘어간 상태를 가시화, issue #12)을 단일 standard batch 로 delivery 한다. 거버넌스는 dcy-017 OQ-3 결정대로 **전부 change-req, 신규 REQ 없음**.
|
||||
- 핵심: snapshot RPC 응답에 holding 슬롯 워치독 상태(`expired`/`last_seen`)를 read-only 동봉(REQ-034/021)하고 `trex-core slots` 가 WATCHDOG-OWNED(전략 이탈)를 표시(REQ-032). safety-sell 의 워치독 소유 진입(WARN)/이탈(INFO)·발동(forced_close·stop_loss=WARN, take_profit·market_close=INFO)을 카운터+구조화 로그로 가시화(REQ-037/038/039). 모든 가시화는 best-effort(청산을 막지 않음). Redis projection·push 알림 미채택(OQ-1 (a)).
|
||||
|
||||
## Scope
|
||||
- In Scope:
|
||||
- snapshot RPC 응답 워치독 상태 필드(best-effort) + `WatchdogStore.last_seen` (REQ-034/021)
|
||||
- `trex-core slots` 워치독 소유 표시 (REQ-032)
|
||||
- safety-sell 워치독 소유 진입/이탈 + 발동(phase 차등 WARN/INFO) 로그 + in-process 카운터 (REQ-037/038/039)
|
||||
- runtime-flows/interface-contract 정합 (REQ-042)
|
||||
- Out of Scope:
|
||||
- 워치독 판정 로직·timeout 기준 변경(가시화만)
|
||||
- WatchdogStore in-memory → 영속 store 승격(정본 변경)
|
||||
- Redis projection·pub/sub push 알림(OQ-1 (a) 미채택) — push 하드 요구 시 후속 분리
|
||||
|
||||
## Documents
|
||||
- Planning: [planning.md](./planning.md)
|
||||
- Design: [design.md](./design.md)
|
||||
- Implementation: [implementation.md](./implementation.md)
|
||||
- Verification: [verification.md](./verification.md)
|
||||
|
||||
## Notes
|
||||
- Source discovery 단일(dcy-017). OQ-1((a) CLI/RPC 노출, Redis 미채택)·OQ-2(차등 매트릭스)·OQ-3(전부 change-req) Answered.
|
||||
- dcy-016 으로 관측 함정(조회가 워치독 리셋) 이미 해소 → 비침습 on-demand 관측으로 issue #12 충족(A-1).
|
||||
- best-effort 격리(NFR-1): _attach_watchdog·_update_ownership·_log_fire 모두 예외 격리, source of truth(in-memory 워치독)·청산 동작 불변.
|
||||
- 메트릭은 in-process 카운터(`SafetySellService.counters`) — 기존 REQ 범위(신규 인프라 없음).
|
||||
- WatchdogStore in-memory → 소유 *상태* 는 재시작 시 소실(폴링 재개 시 재구성), 발동 *로그* 는 이력 유지(R-3).
|
||||
@@ -0,0 +1,50 @@
|
||||
# BAT-021 Planning
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-021
|
||||
- Profile: standard
|
||||
|
||||
## Included REQ
|
||||
- REQ-034 (Interface, change-req): `WatchdogStore.last_seen` + snapshot 워치독 상태 노출.
|
||||
- REQ-021 (Integration, change-req): snapshot 응답 `watchdog[]` 필드.
|
||||
- REQ-037 (Integration, change-req): 워치독 소유 진입/이탈 + forced_close 발동 가시화.
|
||||
- REQ-038 (Integration, change-req): stop_loss(WARN)/take_profit(INFO) 발동 가시화.
|
||||
- REQ-039 (Integration, change-req): market_close 발동 가시화.
|
||||
- REQ-032 (Interface, change-req): `trex-core slots` 워치독 소유 표시.
|
||||
- REQ-042 (Documentation, change-req): runtime-flows/interface-contract 정합.
|
||||
|
||||
## Delivery Plan
|
||||
1. REQ-034/021(서버): `watchdog.py` `last_seen` getter; `messaging_handlers.py` `_attach_watchdog`(best-effort) + `watchdog_timeout_sec` 파라미터; daemon 배선.
|
||||
2. REQ-037/038/039(가시화): `safety_sell.py` `instance_key`/`counters`/`_log_fire`(phase 차등)/`_update_ownership`(소유 진입·이탈) + check_*·run_once 배선; daemon instance_key 배선.
|
||||
3. REQ-032(CLI): `cli.py` `_cmd_slots` 가 watchdog 필드로 WATCHDOG-OWNED 표시.
|
||||
4. REQ-042(문서): runtime-flows(워치독 노출 + safety-sell 가시화 flow), interface-contract(snapshot watchdog 필드).
|
||||
5. 테스트: safety-sell 가시화 + snapshot watchdog 필드 + CLI 표시 + 전체 회귀 + ruff + 인프라 게이트.
|
||||
|
||||
## Dependencies
|
||||
- Internal:
|
||||
- dcy-007/BAT-010·011 safety-sell/워치독(REQ-034/037/038/039) — 가시화 대상.
|
||||
- dcy-016/BAT-020 운영자 CLI `slots`·워치독 억제 읽기(REQ-032/021) — 비침습 관측 기반(A-1).
|
||||
- dcy-011/dcy-013 의 WARN+카운터 가시화 패턴 정합(NFR-3).
|
||||
- External:
|
||||
- 없음(Redis 미채택). in-process 카운터.
|
||||
|
||||
## Design Gate
|
||||
- Design Required Before Implementation: yes
|
||||
- Reason: (a) 가시화 부수효과가 워치독 판정·safety-sell 청산을 절대 막으면 안 됨(R-1/NFR-1) — best-effort 격리 경계를 설계에서 못박아야 안전 기능 회귀를 막는다. (b) 워치독 소유 진입/이탈 diff 의 grace 처리·상태 보관(재시작 소실, R-3)·phase별 로그 레벨 매트릭스(OQ-2)를 설계에서 고정. (c) snapshot 응답에 watchdog 필드 추가가 REQ-028 strict envelope 와 충돌하지 않도록 additive top-level 필드 경계 확정. → design.md 동일 턴 scaffold.
|
||||
|
||||
## Milestones
|
||||
1. M1 — REQ-034/021 watchdog last_seen + snapshot 필드, 핸들러 테스트 green
|
||||
2. M2 — REQ-037/038/039 safety-sell 소유/발동 가시화 + 카운터, 가시화 테스트 green
|
||||
3. M3 — REQ-032 CLI 표시
|
||||
4. M4 — REQ-042 문서 정합
|
||||
5. M5 — 전체 회귀 + ruff + 인프라 게이트
|
||||
|
||||
## Risks
|
||||
- R-1 (High): 가시화가 실패/지연해 워치독 판정·청산을 막음. 대응: _attach_watchdog/_update_ownership/_log_fire 예외 격리, source of truth(in-memory) 불변. (NFR-1)
|
||||
- R-2 (Low, OQ-1): 메커니즘 과잉. 대응: Redis 미채택, CLI/RPC 노출 + 로깅으로 한정.
|
||||
- R-3 (Low): WatchdogStore in-memory → 재시작 시 소유 상태 소실. 대응: live 반영임을 문서화, 발동 로그는 이력 유지.
|
||||
|
||||
## Notes
|
||||
- 1차 게이트: 전체 회귀 green(워치독 판정·safety-sell 트리거 무회귀 — 관측만 추가).
|
||||
- 가시화 테스트는 caplog(WARN/INFO) + counters 단언으로 결정론.
|
||||
- snapshot watchdog 필드는 operator(touch_watchdog=false) 요청으로 비침습 검증(폴링이 last_seen 갱신 안 함).
|
||||
@@ -0,0 +1,71 @@
|
||||
# BAT-021 Verification
|
||||
|
||||
- Status: verified
|
||||
- Batch: BAT-021
|
||||
|
||||
## Acceptance Mapping
|
||||
|
||||
### REQ-034 (워치독 상태 노출, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| snapshot 응답 holding 슬롯 expired/last_seen 노출 | tests/application/test_messaging_snapshot_consumer.py::test_snapshot_exposes_watchdog_state_for_holding_slots |
|
||||
| 관측이 워치독 리셋 안 함(비침습) | ::test_operator_query_suppresses_watchdog_touch (dcy-016 회귀) |
|
||||
| 판정 동작 불변 | tests/application/test_safety_sell_worker.py 전체 회귀 |
|
||||
|
||||
### REQ-021 (snapshot watchdog 필드, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| 응답 watchdog[] shape | test_messaging_snapshot_consumer.py::test_snapshot_exposes_watchdog_state_for_holding_slots |
|
||||
|
||||
### REQ-037 (소유 진입/이탈 + forced_close, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| 소유 진입 WARN + 카운터 | tests/application/test_safety_sell_visibility.py::test_watchdog_ownership_entry_warns |
|
||||
| 소유 이탈 INFO + 카운터 | ::test_watchdog_ownership_exit_on_return |
|
||||
| 안정 시 churn 없음 | ::test_no_ownership_churn_when_stable |
|
||||
| forced_close 발동 WARN + 카운터 | ::test_forced_close_fire_logs_warn |
|
||||
| grace 중 억제 | ::test_grace_period_suppresses_ownership |
|
||||
|
||||
### REQ-038 (SL/TP 발동, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| take_profit 발동 INFO + 카운터 | test_safety_sell_visibility.py::test_take_profit_fire_logs_info |
|
||||
| stop_loss WARN(매트릭스) | _log_fire WARN reasons + forced_close WARN 테스트로 레벨 검증 |
|
||||
|
||||
### REQ-039 (market_close 발동, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| market_close INFO + 카운터 | _log_fire INFO 경로(test_take_profit INFO 동형) + 기존 market_close 회귀 |
|
||||
|
||||
### REQ-032 (CLI 표시, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| slots WATCHDOG-OWNED 표시 | tests/runtime/test_cli_operator.py::test_slots_marks_watchdog_owned |
|
||||
|
||||
### REQ-042 (baseline 문서, change-req)
|
||||
| AC | Evidence |
|
||||
|----|----------|
|
||||
| runtime-flows/interface-contract 정합 | 문서 diff(BAT-021) |
|
||||
|
||||
## Evidence
|
||||
- Test:
|
||||
- 단위 전체 회귀: `335 passed / 34 skipped`(신규 visibility 6 + snapshot 1 + CLI 1 포함; `::test_sandbox_token_and_submit` deselect).
|
||||
- 인프라 게이트(PG trex_core_test + RabbitMQ): `369 passed`.
|
||||
- `ruff check trex_core tests` → All checks passed.
|
||||
- Logs: `335 passed, 34 skipped, 1 deselected` / `369 passed, 1 deselected ~18.1s`.
|
||||
|
||||
## 성공 기준(dcy-017) 대응
|
||||
- S-1(슬롯이 워치독 소유로 넘어감을 운영자가 인지): snapshot watchdog 필드 노출 + CLI WATCHDOG-OWNED 표시 + 소유 진입 WARN.
|
||||
- S-2(소유 접수·발동·이탈 구분 관측, 무성 0): test_safety_sell_visibility(소유 진입/이탈, forced_close WARN, take_profit INFO) + 카운터.
|
||||
- S-3(관측이 last_seen 미갱신): test_operator_query_suppresses_watchdog_touch(dcy-016) — snapshot watchdog 테스트도 operator 요청으로 비침습.
|
||||
- S-4(가시화 실패가 청산 차단 안 함): `_attach_watchdog`/`_update_ownership` try/except 격리(설계), 판정·청산 source of truth 불변 — 기존 safety-sell 트리거 회귀 green.
|
||||
|
||||
## Carried-Over / 비차단
|
||||
- WatchdogStore in-memory → 소유 상태 재시작 시 소실(폴링 재개 시 재구성, R-3). 발동 로그는 이력 유지. 영속 승격은 Out of Scope(별도 주기).
|
||||
- Redis projection·push 알림 미채택(OQ-1 (a)) — push 하드 요구 시 후속 분리.
|
||||
- 메트릭은 in-process 카운터(`SafetySellService.counters`) — 외부 메트릭 시스템 연동은 운영 배포 절차/후속.
|
||||
|
||||
## Result
|
||||
- Ready for Release: true
|
||||
- Blocking Issues:
|
||||
- 없음. 워치독 상태 노출·safety-sell 가시화 모두 단위 green(369 passed 회귀, 판정·청산 무회귀). LIVE sandbox 토큰 deselect 는 `.env` 환경 의존(본 batch 무관).
|
||||
@@ -28,3 +28,4 @@
|
||||
| BAT-018 | standard | release-candidate | REQ-005 (CHG-20260608-01), REQ-048 (CHG-20260608-01), REQ-009 (CHG-20260608-01) | dcy-014 | [bat-018](./bat-018_20260608_trading-date-timezone-daily-preallocation/) |
|
||||
| BAT-019 | standard | release-candidate | REQ-017 (CHG-20260608-01), REQ-019 (CHG-20260608-01), REQ-018 (CHG-20260608-03), REQ-020 (CHG-20260608-01) | dcy-015 | [bat-019](./bat-019_20260608_ledger-outbox-permanent-error-backoff/) |
|
||||
| BAT-020 | standard | release-candidate | REQ-032 (CHG-20260608-01), REQ-022 (CHG-20260608-01), REQ-021 (CHG-20260608-02), REQ-034 (CHG-20260608-01), REQ-026 (CHG-20260608-01) | dcy-016 | [bat-020](./bat-020_20260608_operator-cli-rpc-commands/) |
|
||||
| BAT-021 | standard | release-candidate | REQ-034 (CHG-20260608-02), REQ-021 (CHG-20260608-03), REQ-037 (CHG-20260608-01), REQ-038 (CHG-20260608-01), REQ-039 (CHG-20260608-01), REQ-032 (CHG-20260608-02), REQ-042 (CHG-20260608-01) | dcy-017 | [bat-021](./bat-021_20260608_watchdog-ownership-visibility/) |
|
||||
|
||||
Reference in New Issue
Block a user