feat: initialize cold display guard

This commit is contained in:
Yoilun
2026-04-27 10:59:13 +08:00
commit 36dc3548e6
17 changed files with 918 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
# Cold Display Guard Design
**Date:** 2026-04-27
## Goal
Build a single-camera refrigerated display monitoring service that records how long each food batch remains in each display zone and raises alerts when over-threshold food is removed without confirmed disposal or is placed back into the display.
## Scope
- One camera sees both the refrigerated display cabinet and the trash bin.
- The initial cabinet layout is 4 columns by 2 rows.
- The layout must be configurable because the physical arrangement may change.
- Each zone may contain multiple food items.
- Items in one zone are treated as one batch.
- Mixed batches are not allowed.
- A new batch can only start after a zone becomes empty.
## Architecture
The project separates business state from computer vision:
1. Vision adapters detect display-zone occupancy and trash-bin deposit events.
2. The batch engine receives normalized observations with timestamps.
3. The engine maintains zone and batch state.
4. The notifier layer emits JSONL events and later can send webhooks or UI alerts.
The first implementation focuses on the batch engine and event contract. Camera inference can be added later without changing compliance rules.
## Zone Model
Each zone has:
- `zone_id`
- configured polygon or bounding box
- current observed item count
- optional active batch
The initial default zones are `r1c1` through `r2c4`.
## Batch State Machine
### `active`
Food is currently visible in the zone. The batch has `started_at`, `zone_id`, and current observed count.
### `pending_disposal`
The batch exceeded the maximum dwell time and the zone became empty. The system waits for a trash-bin deposit event within a configurable window.
### `discarded`
The over-threshold batch was removed and a trash-bin deposit was observed in the confirmation window.
### `consumed`
The batch was removed before the maximum dwell threshold. No trash confirmation is required.
### `violation`
The system observed one of these conditions:
- food was added to an already occupied zone, which indicates a mixed batch
- an over-threshold removed batch was put back into any display zone before confirmed disposal
- an over-threshold removed batch was not followed by trash disposal before the confirmation deadline
## Timing Rules
- Default maximum dwell time: 3 hours (`10800` seconds).
- Default trash confirmation window: 2 minutes (`120` seconds).
- A zone changing from `0` to `>0` starts a new batch.
- A zone changing from `>0` to `0` ends the visible dwell period.
- Count decreases while still `>0` do not end the batch.
- Count increases while already `>0` produce a mixed-batch violation.
## Event Contract
The engine emits JSON-compatible events:
- `batch_started`
- `batch_count_changed`
- `batch_consumed`
- `batch_pending_disposal`
- `batch_discarded`
- `mixed_batch_violation`
- `overdue_return_violation`
- `missing_disposal_violation`
Each event includes:
- `event`
- `ts`
- `camera_id`
- `zone_id` when applicable
- `batch_id` when applicable
- timing fields such as `started_at`, `ended_at`, and `dwell_seconds`
## Future Vision Integration
The vision layer should output normalized observations:
```json
{
"ts": "2026-04-27T10:00:00+08:00",
"zone_counts": {
"r1c1": 3,
"r1c2": 0
},
"trash_deposit": false
}
```
Trash disposal confirmation should use motion/object evidence inside the trash ROI, not merely a person standing near the bin.

View File

@@ -0,0 +1,62 @@
# Cold Display Guard Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Build a standalone Python project for refrigerated display food-batch timing and 3-hour disposal compliance alerts.
**Architecture:** Keep camera and model logic outside the first business core. Implement a pure Python batch engine that consumes timestamped zone occupancy and trash-bin events, emits JSON-compatible compliance events, and can later be driven by a video adapter.
**Tech Stack:** Python 3.11+ standard library, TOML config via `tomllib`, tests via `unittest`.
---
### Task 1: Project Skeleton
**Files:**
- Create: `pyproject.toml`
- Create: `src/cold_display_guard/__init__.py`
- Create: `README_zh.md`
- Create: `config/example.toml`
**Steps:**
1. Create packaging metadata with a console script named `cold-display-guard`.
2. Create a Chinese README documenting the confirmed business rules.
3. Create default TOML config for camera id, thresholds, 4x2 zones, and trash ROI placeholder.
4. Verify imports with `python3 -m unittest discover -s tests`.
### Task 2: Batch Engine
**Files:**
- Create: `src/cold_display_guard/models.py`
- Create: `src/cold_display_guard/engine.py`
- Test: `tests/test_engine.py`
**Steps:**
1. Write tests for batch start, normal consumption, over-threshold pending disposal, trash confirmation, mixed-batch violation, overdue return violation, and missing disposal violation.
2. Implement dataclasses for observations, batches, zones, and events.
3. Implement `BatchEngine.process()`.
4. Run `python3 -m unittest tests.test_engine -v`.
### Task 3: Config and CLI
**Files:**
- Create: `src/cold_display_guard/config.py`
- Create: `src/cold_display_guard/cli.py`
- Test: `tests/test_config.py`
**Steps:**
1. Load TOML config into an engine settings dataclass.
2. Add CLI support for processing a JSONL observation file.
3. Write emitted events to stdout as JSONL.
4. Run `python3 -m unittest discover -s tests -v`.
### Task 4: Git
**Steps:**
1. Initialize git in `~/Code/cold_display_guard`.
2. Review `git status --short`.
3. Commit the initial project.