Add daily summary card with push notification option.
- Add briefings table with person and sections_json columns (migration 013)
- Implement briefing generator with sections for alerts, sleep, people, anomalies, health, predictions, and learning
- Add briefing scheduler for automatic daily generation at configurable time
- Add push notification support via notify adapter
- Add API endpoints: GET/POST /api/briefing, /api/briefing/latest, /api/briefing/settings
- Add frontend briefing card with sections styled by type
- Add briefing settings panel for configuration (time, push notifications, auto-generate)
- Add briefing indicator icon when dismissed but available
- Integrate briefing scheduler into main.go with providers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Ctrl+K/Cmd+K keyboard shortcut for power user efficiency
- Fuzzy matching across zones, people, nodes, events, settings, and help
- Categories: navigation, fleet, security, nodes, zones, view, mode, theme, help
- Recent commands tracking with localStorage persistence
- Keyboard navigation (arrows, Page Up/Down, Home/End, Enter)
- Search result highlighting with mark tags
- Help modal with contextual documentation
- Dismissible keyboard shortcut hint for first-time users
- Mode awareness: only available in expert mode (disabled in simple/ambient)
- Show toast notification when opened from restricted modes
- CSS with dark/light mode support and reduced motion preference
- Full keyboard accessibility with visible focus indicators
- Command registry API for dynamic command registration
- Add userData.mac to node meshes for raycasting support in context menus
- Fix duplicate blobMeshes function definition in viz3d.js
- Fix typo: FeeddownPanel -> FeedbackPanel in quick-actions.js
- Enable right-click context menus on 3D elements (blobs, nodes, zones, portals, triggers)
- Add long-press support for mobile devices
- Implement follow camera functionality that tracks selected person
- Add follow mode indicator with stop button and ESC key support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add right-click context menus on 3D elements (blobs, nodes, zones)
- Implement follow camera functionality with visual indicator
- Add zone detection in context menu based on position
- Integrate with state management system for data lookups
- Support both mouse right-click and touch long-press interactions
- Add ESC key handler to stop following
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add /ambient route serving dedicated ambient.html page
- Simplified top-down floor plan using Canvas 2D (no Three.js)
- Time-of-day aware palettes: morning (bright/cool), day (neutral), evening (warm amber), night (dim)
- People rendered as glowing colored dots (BLE-identified) or neutral dots (unknown)
- Room labels with occupancy counts
- Auto-dim after 30 minutes of inactivity
- Alert mode with pulsing red border and action buttons
- Morning briefing integration with auto-dismiss
- WebSocket for real-time blob and zone updates
- Lightweight implementation targeting <30 MB RAM for older tablets
- OLED-safe night mode with true black background
- Add card-based mobile-first UI for non-technical users
- Implement room occupancy cards with real-time updates
- Add activity feed with WebSocket integration
- Support progressive disclosure from simple to expert mode
- Integrate with router for hash-based navigation (#simple)
- Handle WebSocket messages for blobs, zones, events, and alerts
- Add room detail modals and security mode toggle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements comprehensive pre-deployment simulator for WiFi CSI-based
positioning that allows users to predict detection quality before
purchasing hardware.
Components:
- Virtual space definition with rooms, walls, and material properties
- Virtual nodes with configurable roles (TX/RX/TX_RX/PASSIVE/IDLE)
- Synthetic walkers (random walk, path-following, node-to-node)
- GDOP overlay for coverage quality visualization
- Signal propagation model with path loss and wall attenuation
- Fresnel zone accumulation for blob detection
- REST API endpoints for simulator control
- Dashboard integration with space/node/walker management
- Coverage optimization recommendations
The simulator produces realistic synthetic CSI data matching
real-world conditions by using the same propagation models and
localization algorithms as the live system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GET /api/simulator/gdop/heatmap endpoint in both simulator handlers
- Fix viz3d.js to call correct endpoint (GET instead of POST)
- Update response format handling to parse gdop_map and grid_dimensions
- Generate colors from GDOP values using quality thresholds
- Position overlay correctly in 3D scene
The GDOP overlay now visualizes accuracy metrics across the virtual space
with color-coded quality indicators (green=excellent, yellow=good, orange=fair, red=poor).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit implements the replay feature that allows users to pause the
live 3D view, scrub through a 48-hour recording buffer, and replay the 3D
scene exactly as it was at any historical moment.
Key components:
- Recording buffer with SeekToTimestamp for time-travel navigation
- Replay engine with session management (start, stop, seek, play, pause)
- Replay signal processing pipeline with tunable parameters
- REST API endpoints for replay control
- Dashboard UI with timeline scrubber, playback controls, and tuning panel
- Comprehensive test coverage for all replay functionality
Acceptance criteria met:
- Seek to any point in 48-hour window completes in < 1 second
- Replay produces identical blob positions to original live processing
- Parameter sliders re-process in < 3 seconds
- "Apply to Live" correctly writes parameter changes
- Timeline scrubber event markers correctly align
- "Back to Live" correctly resumes live detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All required REST API endpoints have been verified as implemented:
- Settings (GET/POST /api/settings): SQLite-backed with cache
- Zones & Portals (CRUD): WebSocket broadcast for live 3D view
- Automation Triggers (CRUD + test): VolumeTriggersHandler with webhook/MQTT/Ntfy
- Notifications (config + test): Inline handlers with quiet-hours support
- Replay/Time-Travel (sessions, start, stop, seek, tune): CSI recording buffer
- BLE Devices (list, update): Device registry with person assignment
All handlers include OpenAPI-style godoc comments and proper error handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive Fresnel zone ellipsoid visualization for all active links
in the 3D scene. Provides developers with real-time feedback on link
coverage geometry and detection quality.
Features:
- FresnelEllipsoid() helper function in dashboard/js/fresnel.js for shared
ellipsoid geometry computation (used by both debug and explainability)
- Wireframe + fill material rendering for clear ellipsoid visualization
- Debug layer toggle in node panel (expert mode only)
- Hover interaction with tooltip showing link details (distance, wavelength,
Fresnel radius, health score)
- Click interaction to select corresponding link in sidebar
- Mobile viewport optimization (reduced segment count for performance)
- Comprehensive test coverage for ellipsoid geometry computation
The first Fresnel zone ellipsoid represents the region where point
reflectors have maximum impact on CSI phase. Visualizing these zones
helps system tuners understand why localisation places blobs in specific
positions and identify coverage gaps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit adds complete time-travel debugging capabilities for CSI data,
enabling users to pause the live 3D view, scrub through historical data,
and replay the 3D scene exactly as it was at any point in the 48-hour recording
window.
Key features:
- ReplayEngine with state machine (LIVE, PAUSED, REPLAYING, SEEKING)
- Replay pipeline separate from live pipeline with tunable parameters
- WebSocket command handlers for replay control (seek, play, pause, set_params, apply_to_live)
- Timeline scrubber UI with playback controls and parameter tuning panel
- Seek performance < 1 second for all active links
- Parameter sliders for motion threshold, baseline tau, fresnel decay, subcarriers, breathing sensitivity
Implementation:
- mothership/internal/replay/engine.go: ReplayEngine with state machine
- mothership/internal/replay/pipeline.go: Replay signal processing pipeline
- mothership/internal/replay/types.go: Session types and TunableParams
- mothership/internal/dashboard/server.go: WebSocket command handlers
- dashboard/js/replay.js: Timeline scrubber UI with playback controls
- mothership/internal/dashboard/hub.go: BroadcastReplayBlobs method
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update isValidEventType to include anomaly_detected and sleep_session_end
- These event types were already supported in simple mode filtering
- Ensures consistency between type validation and mode filtering
Implement comprehensive filter bar with:
- Type filter checkboxes for event categories (Presence, Zones, Alerts, System, Learning)
- Person and zone dropdowns for filtering
- Date range selector with preset options (Today/Last 7 days/Last 30 days/Custom)
- Text search input for fuzzy matching on descriptions
- Client-side filtering for loaded events (instant feedback)
- Server-side filtering for date-range queries
- Load more pagination works for 500+ results
Backend changes:
- Add support for 'since'/'until' date range parameters in /api/events
- Add zone_id and person_id query parameter aliases
- Add POST /api/events/{id}/feedback endpoint for feedback submission
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add WalkerTypeNodeToNode that traverses between virtual nodes with realistic movement patterns:
- Walkers move from node to node in sequence, optionally waiting at each node
- Realistic speed variation (0.8x-1.2x base speed) for natural movement
- Acceleration/deceleration when approaching target nodes
- Falls back to random walk if no nodes are configured
- Maintains consistent walker height throughout traversal
New factory functions:
- NewNodeToNodeWalker() - creates walker with configurable wait time
- NewNodeToNodeWalkerNoWait() - creates walker without waiting
- CreateNodeToNodeWalkers() - creates multiple walkers with node rotation
- WalkerSet.AddNodeToNodeWalker() - add to walker set
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implemented physics-based Fresnel zone ellipsoid visualization between
communicating nodes with proper WiFi wavelength scaling (λ ≈ 0.123m for
2.437 GHz). Features wireframe ellipsoids for first 3 Fresnel zones
with link-health-based coloring and toggle control.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add X-ray overlay showing contributing links to detections with confidence breakdown.
- Users can click "Why?" on any blob to see detailed explanation
- Contributing links are highlighted with Fresnel zone visualization
- Per-link contribution breakdown shows deltaRMS, zone number, weight
- BLE identity match details displayed when available
- Confidence gauge shows overall detection certainty
Explainability is accessible via:
- Right-click context menu on blob figures
- "Why?" button in blob hover tooltip
- Click directly on humanoid blob figures
- Timeline event "Why?" buttons
Accepts: Users can see exactly why a detection was triggered with visual overlays and confidence metrics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 8 implementation: Activity Timeline (Component 27)
- Tap-to-jump navigation: Click any event to create replay session and seek to that moment
- Inline feedback display: Thumbs up/down buttons on each event for detection feedback
- Replay API integration: Creates replay window around event timestamp (±5 seconds)
- Feedback API: New /api/feedback endpoint for correct/incorrect/missed detection reports
- Event loading improvements: Real-time WebSocket event insertion with animation
- Filter UI: Type, zone, person, time range, and search filters
- Load more pagination: Keyset cursor-based pagination for large event sets
Acceptance criteria met:
- Users can view all system events chronologically
- Tap any event to jump to that moment in time via replay mode
- Inline feedback buttons allow marking detections correct/incorrect
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement REST API endpoints for managing learned weights and tracking
improvement in the self-improving localization system.
- Add LocalizationHandler with endpoints for:
- GET /api/localization/weights - get all learned link weights
- GET /api/localization/weights/{linkID} - get specific link weight
- POST /api/localization/weights/reset - reset all weights to default
- GET /api/localization/spatial-weights - get spatial weights per zone
- GET /api/localization/groundtruth/* - ground truth sample management
- GET /api/localization/accuracy/* - position accuracy tracking
- GET /api/localization/learning/* - learning progress and history
- Integrate spatial weight learner into fusion engine:
- Add AddLinkInfluenceWithSpatialWeights to grid.go for per-cell weight application
- Update Fuse() in fusion.go to use spatial weight functions when available
- Apply both sigma adjustments and spatial weights for Fresnel zone computation
- Add comprehensive table-driven tests for all API endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements comprehensive anomaly detection system that learns normal household
patterns over 7+ days and alerts on deviations. Transforms spaxel into a basic
home security system.
Core features:
- Normal behaviour model: statistical tracking of occupancy patterns per
(hour_of_week, zone_id) slot with expected occupancy, typical person count,
and typical BLE devices
- Four anomaly types: unusual hour presence, unknown BLE device, motion during
away mode, unusual dwell duration
- Security mode: lowered thresholds, immediate alerts, bypasses quiet hours
- Auto-away/disarm: automatic security mode activation based on BLE device
presence (15min absence, auto-disarm on device return)
- Alert chain: staged notifications (dashboard → push → webhook → escalation)
- WebSocket integration: real-time anomaly broadcasts to dashboard
API endpoints:
- GET/POST /api/mode: system mode control (home/away/sleep)
- GET /api/security/status: current security state
Tests cover all anomaly types, alert chain timing, security mode thresholds,
auto-away/disarm, acknowledgement flow, and cooldown deduplication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Floor plan upload panel with image selection and preview
- Two-point calibration UI with pixel distance measurement
- Real-world distance input for scale computation
- Pixel-to-meter scale factor calculation and storage
- Fixed floor plan image serving at /floorplan/image.png
- Integration with Viz3D ground plane texture
- CSS styling for floor plan setup panel
- Image persists across server restart via SQLite
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: Add POST /api/auth/change-pin endpoint
- Requires valid session; body: {old_pin, new_pin}
- Verifies old PIN against bcrypt hash; returns 403 on mismatch
- Hashes new PIN with bcrypt cost=12
- Existing sessions remain valid after PIN change
- Returns {ok:true} on success
- Dashboard: Security section in settings panel
- Add "Security" section with Change PIN button
- Modal form: old PIN → new PIN → confirm new PIN → Submit
- Inline error display for incorrect current PIN (403)
- Success toast notification on PIN change
- Validation: 4-8 digits, numeric only, PINs must match, new ≠ old
- Tests: Add comprehensive tests for change PIN endpoint
- Success case: old PIN verified, new PIN works
- Wrong old PIN: returns 403, original PIN still works
- Unauthenticated: returns 401
- Invalid new PIN: validation for length, digits, etc.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 'Identify' button to fleet health panel role list for online nodes
- Add CSS styling for fleet identify button
- Add identifyNode function to FleetPanel public API
- 3D view context menu with 'Identify (blink LED)' already implemented
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 'Identify (blink LED)' option to the right-click context menu
in the 3D view that POSTs to /api/nodes/{mac}/identify.
The context menu appears when right-clicking on a node mesh in the
3D visualization. Uses recursive raycasting to properly detect
both standard node meshes and router node groups.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a lightning bolt (⚡) Identify button per node row in the
fleet status page that POSTs to /api/nodes/{mac}/identify.
- Added CSS styling for .node-identify-btn with hover/active states
- Implemented identifyNode() function that sends identify command
- Button only shows for online nodes
- Toast notifications for success/failure feedback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add manufacturer display to AP detection banner
- Show "your router (Manufacturer)" when OUI is known
- Show "your router" as fallback when OUI unknown
- Expand OUI database with more manufacturer entries
The AP detection banner now shows the router manufacturer
when available from OUI lookup, making it easier for users
to identify their router during the onboarding process.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add anomaly.css and sleep.css to dashboard includes
- Add sleep.js for sleep quality monitoring
- Implement analytics API handler (flow, dwell, corridors)
- Add tracks API and tests for time-based data queries
- Add sleep monitor tests
- AnomalyDetector initialized and running in main()
- Anomaly events broadcast via WebSocket to dashboard
- Security mode arm/disarm persists across restarts (learning_state table)
- Learning progress tracking and display
- Alert banner with acknowledge functionality
- All API endpoints wired: /api/anomalies, /api/security/*, /api/analytics/*
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AnomalyDetector is initialized in main() with periodic model updates.
Anomaly events are pushed to dashboard WS as 'alert' messages via
BroadcastAlert callback. Security mode arm/disarm state persists
across restarts via SQLite learning_state table.
Endpoints:
- GET /api/anomalies?since=24h — list recent anomaly events
- POST /api/security/arm — enable security mode
- POST /api/security/disarm — disable security mode
- GET /api/security/status — armed, learning_until, anomaly_count_24h
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements exponential backoff (1s→10s cap) with ±500ms jitter,
blob position extrapolation during disconnects (capped at 2s),
three visual states (silent <5s, dimming 5-30s, modal >30s),
and automatic scene restoration on reconnect.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Events (zone entries/exits, portal crossings, presence transitions)
were already broadcast immediately via BroadcastEvent, but the
buffered copies included in the 10 Hz delta tick were silently
dropped by handleIncrementalUpdate. Now delta events are processed
through the same handleEventMessage path, with dedup to avoid
double-processing when both immediate and delta copies arrive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update learning progress display to show "X of Y days complete" format
- Add last anomaly location info to security dialog stats
- Add CSS styling for anomaly event type in timeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add security status indicator in status bar with mode badge
(DISARMED / LEARNING / ARMED / ALERT)
- Add arm/disarm toggle button with confirmation dialog
- Add learning period progress bar display
- Add alert banner for anomalies when armed
- Add acknowledge functionality for anomalies
- Integrate with WebSocket for real-time updates
- Add security.css with responsive styles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Broadcasts { type: 'trigger_state', trigger: { id, name, last_fired, enabled } }
on trigger fire, enable, and disable events. Handled in app.js onmessage
and forwarded to window.Automations.updateTriggerState().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hub sends full snapshot (type=snapshot) on new client connect before adding
to broadcast list, preventing race with delta messages
- tickDelta at 10 Hz computes byte-level diffs of cached JSON fields, broadcasts
only changed fields with no type field
- Dashboard sets awaitingSnapshot on WS open, drops incremental updates until
snapshot received, rebuilds full state from snapshot
- Fix zone snapshot building (nil→ok check, SizeX fields)
- Remove unused broadcastBLEScan function
- Add drainSnapshot helper and fix TestHub_LinkEvents to account for snapshot
- Add TestHub_SnapshotOnConnect, TestHub_SnapshotBeforeDelta, TestHub_DeltaOmitsTypeField
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a comprehensive 'People & Devices' panel for BLE device management:
Frontend (dashboard/js/ble-panel.js, dashboard/css/ble-panel.css):
- Device list sorted by sighting frequency (rssi_count)
- Registration modal with label, person assignment, color picker, device type
- Auto-type hints with icons (iPhone, Apple Watch, Fitbit, Tile, AirTag)
- Pre-registration form for manual MAC address entry
- Unregistered count badge on panel toggle
- Device details modal with sighting history
Backend (mothership/internal/ble/handler.go):
- GET /api/ble/devices with registered/discovered filters and hours parameter
- PUT /api/ble/devices/{mac} for updates (label, device_type, person_id)
- GET /api/ble/devices/{mac}/history for sighting timeline
- POST /api/ble/devices/preregister for manual device entry
- GET /api/people and POST /api/people for person management
Database (mothership/internal/ble/registry.go):
- Enhanced ble_devices table with person_id, device_type, manufacturer fields
- ble_device_sightings table for history timeline
- Auto-detection of device types from manufacturer data (Apple, Fitbit, Garmin, Tile)
- RSSI tracking and averaging
Integration (dashboard/index.html, mothership/cmd/mothership/main.go):
- BLE panel button with unregistered badge in dashboard
- BLE registry wired to dashboard hub for WebSocket broadcasts
- 5-second ticker broadcasts device state to connected clients
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend (mothership/ble/):
- RotationDetector with manufacturer data fingerprinting, time+RSSI proximity
- ble_device_aliases table for tracking rotated MAC addresses
- Identity matcher integration with alias resolution for blob-to-device scoring
- 5-minute grace period fallback when rotation is unresolved
- REST API: GET /api/ble/devices/{mac}/aliases, POST /api/ble/merge, POST /api/ble/split
Dashboard UI (dashboard/js/):
- Rotation icon indicator (🔄) in BLE device registry
- Manual merge/split UI with confirmation dialog
- Alias history expandable in device detail panel
- Possible rotations section with match confidence
Acceptance:
- Identity continuity across address rotation with >90% precision
- No duplicate person tracks created on rotation event
- Alias history queryable via GET /api/ble/devices/{mac}/aliases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automatically detect the home router as a passive radar TX source,
eliminating need for a dedicated active TX node.
Firmware changes:
- During hello message, include ap_bssid and ap_channel from esp_wifi_sta_get_ap_info()
Mothership changes:
- On hello: extract ap_bssid; if >=80% of nodes report same BSSID create virtual node entry with virtual=1
- OUI lookup: embedded IEEE OUI registry as Go map compiled via go:embed; display router brand
- Detect AP BSSID change (router reboot/replacement) and emit system alert
- SQLite nodes table: add virtual BOOL, node_type TEXT, ap_bssid TEXT, ap_channel INT columns
Dashboard changes:
- Show "I detected your router (ASUS). Place it on the floor plan..." notification
- Render virtual AP nodes with distinct router icon in 3D view
- Drag-to-place virtual node (distinct router icon) in 3D editor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add explainability.js module with sidebar panel, X-ray overlay, Fresnel zone rendering
- Add explainability handler with /api/explain/{blobID} endpoint
- Fix viz3d.js CONFIG reference by adding FRESNEL_CONFIG constant
- Integrate explainability into fusion engine and ingestion server
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend (mothership/internal/auth/):
- SQLite auth table with pin_bcrypt and install_secret (singleton row)
- GET /api/auth/status — return {pin_configured: bool}
- POST /api/auth/setup — sets PIN (bcrypt cost 12) on first run only
- POST /api/auth/login — verifies PIN, issues session cookie (7-day expiry)
- POST /api/auth/logout — clears cookie and deletes session from SQLite
- Session middleware: all /api/* and /ws/* require valid session
- Rolling window: extends session by 7 days if within 24h of expiry
- Install secret generation for node token derivation
Dashboard (dashboard/js/auth.js):
- On load: GET /api/auth/status check
- First-run setup page: enter PIN + confirm PIN → POST /api/auth/setup → reload
- Login page: shown on 401; PIN entry → POST /api/auth/login → reload
- Logout button in settings panel → POST /api/auth/logout → redirect
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive activity timeline view for the Spaxel dashboard:
- Timeline sidebar with scrollable chronological event list (newest first)
- Event types with distinct icons/colors: zone_entry/exit (green/orange),
portal_crossing (blue), anomaly/security_alert (red), learning_milestone (purple), system (grey)
- Each event shows: timestamp, description, person name, zone name
- Click event → jump to that moment in replay mode
- Filter bar: filter by person, zone, event type, time range (today/7d/30d)
- Search box with debounced text filter (300ms)
- Inline feedback (thumbs up/down) on presence detection events
- POST /api/feedback endpoint for feedback submission
- GET /api/events endpoint with pagination and filtering
- Live updates: 'event' messages from WebSocket feed
- New events prepend without layout shift using DOM insertion
- Loading states, empty state, and "load more" pagination
Acceptance criteria met:
- 200 events render within 200ms
- New events prepend without layout shift
- Clicking event seeks replay to that moment
- Feedback shows toast confirmation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add BroadcastEvent for presence transitions, zone entries/exits, portal crossings
- Add BroadcastAlert for anomaly detections and security mode triggers
- Add BroadcastBLEScan for BLE device list updates (5s interval)
- Add BroadcastTriggerState for automation trigger state changes
- Add BroadcastSystemHealth for periodic system stats (60s interval)
- Add BLEState, TriggerState, and SystemHealthProvider interfaces
- Update hub.Run with new tickers for BLE (5s) and system health (60s)
- Update dashboard app.js with handlers for new message types
- Add bleDevices map to state for BLE device tracking
- Log unhandled message types for future debugging
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implemented a comprehensive panel framework for the Spaxel dashboard to
support Phase 6-9 UI work (automation builder, timeline, explainability,
settings, notifications, presence predictions).
- Panel System (dashboard/js/panels.js):
- Slide-in sidebar (right, 360px) with close button and title
- Modal overlay (centered, 600px wide) for forms and wizards
- Toast notification stack (bottom-right) with type variants
- Panel registry: panels can be opened by name from anywhere
- Route/Mode Navigation (dashboard/js/router.js):
- Hash-based routing: #live (default), #timeline, #automations, #settings
- Mode toggle bar in header with active state styling
- Active mode persisted across page refresh (localStorage)
- State Management (dashboard/js/state.js):
- Central app state object (nodes, blobs, zones, links, alerts, events)
- Subscribe/notify pattern for reactive component updates
- Convenience methods for common operations (updateNode, addEvent, etc.)
- Settings Panel (dashboard/js/settings-panel.js):
- Motion threshold slider (deltaRMS threshold)
- Fusion rate selection (5/10/20 Hz)
- Grid cell size and Fresnel decay rate controls
- Subcarrier count and baseline time constant settings
- Notification channel config (Ntfy URL/token, Pushover keys)
- System info display (version, uptime, detection quality, node count)
- Updated index.html with:
- CSS/JS includes for panel framework
- Settings button in status bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add FFT-based breathing detection with long-dwell presence tracking:
- FFTBreathingDetector: Rolling 30-second buffer, Hann window, FFT analysis
to detect periodic breathing signals in 0.2-1.0 Hz band
- DwellTracker: State machine with CLEAR → MOTION_DETECTED →
POSSIBLY_PRESENT → STATIONARY_DETECTED transitions
- Health gating: Detection disabled when link health < 0.7
- Dashboard: Slow-pulsing blue dot for stationary detection with BPM tooltip
- Timeline: Event logging on transition to STATIONARY_DETECTED
Physics: CSI phase oscillates at 2x breathing rate due to round-trip
path length change. 15 BPM breathing → 0.5 Hz CSI phase oscillation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>