- Emote face is now stable all day; /wake picks a fresh random face each morning instead of rotating every 5 minutes. Removes EMOTE_ROTATION_INTERVAL and last_emote_change entirely. - Added 10 new synthesized sounds for /notify: doorbell, knock, ding, blip, siren, tada, ping, bubble, fanfare, and alarm (loops until tapped or TTL expires). stopAlarm() wired into tap handler and handleStateChange(). - openapi.yaml: new sound names added to enum. - CLAUDE.md / README.md updated to reflect both changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.3 KiB
SPEC.md: Project "Sentry-Emote"
1. Overview
Purpose: Repurpose an old Pixel phone (OLED screen) as an ambient, glanceable system status monitor for a home server. Design Philosophy: Minimalist, binary-state, and high-signal. Use an "Emote" (ASCII/Emoji) to represent system health instead of complex graphs. Target Device: Android Pixel (accessed via Fully Kiosk Browser).
2. System Architecture
The system follows a decoupled Publisher/Subscriber model to ensure extensibility.
- Aggregator (The Broker): A central Python service running on the server. It manages the event queue and generates the state.
- Detectors (The Publishers): Independent scripts (Python, Bash, etc.) that monitor specific system metrics and "hook" into the Aggregator.
- Emote-UI (The Subscriber): A mobile-optimized web frontend that displays the current highest-priority emote.
3. Data Specification
3.1 status.json (State Registry)
The Aggregator outputs this file every time the state changes.
{
"current_state": "optimal",
"active_emote": "( ^_^)",
"color": "#00FF00",
"animation": "breathing",
"message": "All systems nominal",
"active_events": [
{
"id": "disk_check",
"priority": 4,
"message": "Disk 40% full"
}
],
"last_updated": "2026-02-02T17:30:00"
}
3.2 Priority Hierarchy
| Level | Name | Priority | Emote | Color | Logic |
|---|---|---|---|---|---|
| 1 | Critical | Emergency | ( x_x) |
Red | Overrules all. Manual clear required. |
| 2 | Warning | Caution | ( o_o) |
Yellow | Overrules Optimal. Auto-clears if fixed. |
| 3 | Notify | Event | ( 'o') |
Blue | Transient. TTL (Time To Live) of 10s. |
| 4 | Optimal | Default | ( ^_^) |
Green | Active when no other events exist. |
4. Component Requirements
4.1 Aggregator (aggregator.py)
- Event Bus: Accept HTTP POST requests or watch a specific file/directory for new event signals.
- State Management: Maintain a list of "Active Events."
- TTL Logic: Automatically remove Priority 3 events after 10 seconds.
- Deduplication: If multiple events exist, always select the one with the lowest priority number for the
active_emotefield.
4.2 Emote-UI (index.html)
-
OLED Optimization: Pure black background (
#000000). -
Glanceability: Massive centered text for the emote.
-
Animations: -
breathing: Slow opacity/scale pulse. -
shaking: Rapid X-axis jitter for Critical. -
popping: Scale-up effect for Notifications. -
Refresh: Long-polling or
setIntervalevery 2 seconds.
4.3 Extensibility (The Hook System)
- New detectors must be able to send an event to the Aggregator without modifying the core code.
- Example Detector Hook:
curl -X POST -d '{"id":"ssh","priority":1}' http://localhost:5000/event
5. Implementation Roadmap
- Phase 1: Build the
aggregator.pywith basic JSON output. - Phase 2: Build the OLED-friendly
index.htmlfrontend. - Phase 3: Create the first "Detector" (e.g., a simple disk space checker).
- Phase 4: Implement TTL for transient notifications.