feat: upload alarm snapshots to webhook payloads

This commit is contained in:
2026-06-09 13:01:15 +08:00
parent 523f928303
commit 04729a0fd1
14 changed files with 853 additions and 23 deletions

View File

@@ -0,0 +1,111 @@
# Alarm Snapshot Upload Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Capture one current-frame snapshot for alerting runtime events, upload it to the OTA chunk-upload service, and include the returned path in outbound webhook payloads.
**Architecture:** Keep `BatchEngine` unchanged and treat snapshot upload as runtime-side enrichment. Reuse the already captured RGB frame from the active detection loop, encode it to JPEG with `ffmpeg`, upload it through the documented token/init/chunk/complete flow, then merge the returned `object_key` into the webhook payload for alert-level batch events and the derived case events from the same cycle.
**Tech Stack:** Python 3.12 standard library backend, existing `ffmpeg` dependency, JSONL webhook retry flow, unittest.
---
### Task 1: Snapshot Upload Client
**Files:**
- Create: `src/cold_display_guard/alarm_snapshots.py`
- Test: `tests/test_alarm_snapshots.py`
- [ ] **Step 1: Write the failing test**
Add tests that cover:
- loading upload settings from config
- encoding a current RGB frame into JPEG via injected encoder helper
- successful OTA upload flow returning `object_key`
- disabled or non-alert events skipping upload
- [ ] **Step 2: Run test to verify it fails**
Run: `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_alarm_snapshots.py -v`
Expected: FAIL because the snapshot upload module does not exist yet.
- [ ] **Step 3: Write minimal implementation**
Implement:
- upload settings parsing with defaults for `https://ota.zhengxinshipin.com` and secret `change-me-in-production`
- current-frame JPEG encoding
- token/init/chunk/complete upload workflow with injectable HTTP helpers for tests
- per-cycle alert snapshot metadata structure carrying `object_key`, file name, and upload status
- [ ] **Step 4: Run test to verify it passes**
Run: `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_alarm_snapshots.py -v`
Expected: PASS
### Task 2: Runtime And Webhook Integration
**Files:**
- Modify: `src/cold_display_guard/main.py`
- Modify: `src/cold_display_guard/webhooks.py`
- Test: `tests/test_main.py`
- Test: `tests/test_webhooks.py`
- [ ] **Step 1: Write the failing test**
Add tests that cover:
- runtime uploads one snapshot when a cycle contains alert-severity events
- webhook payload includes uploaded `object_key` for alert batch events
- derived case webhook payload includes the same snapshot path for matching case-creation events
- upload failure does not block webhook delivery and instead records failure metadata in payload
- [ ] **Step 2: Run test to verify it fails**
Run:
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_main.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_webhooks.py -v`
Expected: FAIL because runtime/webhook code does not accept snapshot metadata yet.
- [ ] **Step 3: Write minimal implementation**
Implement:
- alert event selection based on event severity
- one-per-cycle snapshot upload using the current frame
- payload enrichment for batch-event and matching case-event webhooks
- retry queue persistence of the already enriched payload
- [ ] **Step 4: Run test to verify it passes**
Run:
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_main.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_webhooks.py -v`
Expected: PASS
### Task 3: Config, Secrets, Docs, And Final Verification
**Files:**
- Modify: `src/cold_display_guard/config.py`
- Modify: `src/cold_display_guard/manage_api.py`
- Modify: `config/example.toml`
- Modify: `README_zh.md`
- Test: `tests/test_config.py`
- Test: `tests/test_manage_api.py`
- [ ] **Step 1: Write the failing test**
Extend tests so:
- config formatting writes snapshot-upload settings
- management config payload strips sensitive upload secret
- [ ] **Step 2: Run test to verify it fails**
Run:
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_config.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_manage_api.py -v`
Expected: FAIL because snapshot upload settings are not exposed/formatted yet.
- [ ] **Step 3: Write minimal implementation**
Implement:
- config keys for snapshot upload URL, secret, object prefix, enable flag, and timeout/chunk settings
- config payload secret stripping
- README updates for alert snapshot upload behavior and returned webhook fields
- [ ] **Step 4: Run targeted and full verification**
Run:
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_alarm_snapshots.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_main.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_webhooks.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_config.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest tests/test_manage_api.py -v`
- `eval "$(/opt/homebrew/bin/pyenv init -)" && PYTHONPATH=src python -m unittest discover -s tests -v`
- `cd web && pnpm build`
Expected: PASS