Delete compiled Go binaries (sim, spaxel-sim, cmd/sim/spaxel-sim, mothership/{sim,spaxel-sim},
*.test, acceptance.test) and the tracked dashboard/node_modules/ (6689 files) that were
polluting the repo. Add .gitignore rules so they stay out. Dashboard deps regenerate via npm ci.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All functionality specified in the task is already in place:
- HA discovery configs published with retain=true on first connect
- Discovery re-published when zones/persons are added/renamed via callbacks
- Empty retained payload published on zone/person deletion
- MQTT command subscriptions wired (rebaseline, security_mode, system_mode)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The MQTT command/rebaseline and HA auto-discovery lifecycle management
were already implemented. Only removed an unused stub function that was
causing compilation to fail.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add CollisionDetector in fleet/collision.go that tracks frame arrivals from TX nodes
- Detect collisions when CSI frames from different TX nodes arrive within 3ms
- Calculate collision rate over 60-second sliding window
- Trigger adaptive re-stagger when collision rate exceeds 5% threshold
- Re-stagger generates random slot offsets to break up persistent collisions
- Rate limit re-stagger to minimum 30-second intervals
- Integrate with ingestion server to record frame arrivals
- Integrate with fleet manager to push updated config messages on re-stagger
- Add comprehensive unit tests for collision detection logic
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Added dashboard/static/js/fleet.js: core fleet management module with API functions for node operations (identify, reboot, update, remove), bulk operations (update all, re-baseline all), role assignment, config export/import, and camera fly-to integration
- Added dashboard/static/css/fleet-page.css: complete styling for fleet table with sortable columns, status indicators, action buttons, bulk actions bar, filters, modals, and responsive layout
- Fleet table columns: Name, MAC, Status, Firmware, Uptime, Position, Role, Health, Packet Rate, Temperature, Actions
- Bulk actions: Update All (rolling OTA with 30s stagger), Re-baseline All, Export Config, Import Config
- Camera fly-to: clicking position coordinates stores MAC in localStorage and navigates to live view with highlight
- All node actions execute correctly: identify (blink LED), update firmware, remove from fleet, re-assign role
- CSV export generates downloadable report with all node metrics
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Features implemented:
- Full table with sortable columns: Name, MAC, Role, Position, Firmware, RSSI, Status, Uptime, Actions
- Role dropdown for changing node roles
- Position column with camera fly-to on click
- Firmware version with update badge
- Bulk actions: Update All, Re-baseline All, Export Config, Import Config, CSV Report
- Node actions: Restart, Update, Remove, Identify (blink LED)
- Responsive design for desktop and mobile
- Toast notifications and modal dialogs
Complete mobile touch interaction support for the 3D expert dashboard:
- Touch orbit/pan/zoom: Single-finger rotate, two-finger pan, pinch-zoom
(Three.js OrbitControls native support)
- Hamburger menu for panel navigation: Collapsible sidebar with:
* Fleet Status
* Zones
* Automation Triggers
* Settings
- Bottom sheet panels on mobile: Slide-up panels with drag-to-close
gesture, 70vh max height, safe-area inset support
- Touch-optimized buttons: Minimum 44×44px tap targets throughout
- No hover-dependent UI: All interactions work via touch
- Long-press context menu: Mobile replacement for right-click
Files:
- dashboard/static/js/mobile.js - Mobile interaction controller
- dashboard/static/css/mobile.css - Mobile-specific styles
Acceptance:
✓ Three.js scene responds to touch gestures
✓ Hamburger menu opens panel navigation
✓ Panels slide in from bottom on mobile
✓ All buttons are touch-friendly (≥44px)
✓ No features require hover
✓ Long-press context menu works on mobile
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add hamburger menu for mobile panel navigation
- Create bottom sheet panels that slide from bottom on mobile
- Implement touch-optimized UI with 44x44px minimum tap targets
- Add mobile-specific panel content for Fleet Status, Zones, Triggers, Settings
- Support drag-to-close gesture on bottom sheets
- Maintain existing desktop panel behavior
- Integrate with existing systems (Viz3D, SpaxelPanels, SpatialQuickActions)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Proactive contextual help that appears when users encounter problems,
but never when things are working well.
Trigger conditions:
- Detection quality drop: Zone-level quality below 60% for >24h
triggers helpful banner with guided diagnostics flow
- Repeated setting changes: Same settings key modified 3+ times
within 60-minute sliding window triggers helpful hint
- Node offline: Any node offline for >2 hours shows troubleshooting
- First-time feature discovery: Brief tooltip shown once per feature
- After false positive feedback: Inline response explaining adjustments
- After successful calibration: Positive reinforcement message
Implementation:
- ZoneQualityTracker: Tracks per-zone detection quality, triggers
callbacks when quality degrades
- EditTracker: Monitors settings edits for repeated changes
- FleetNotifier: Tracks node offline events
- DiscoveryTracker: Manages first-time feature tooltips
- API endpoints: /api/guided/* for diagnostics and feedback
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Implemented proactive contextual help that appears when users encounter
problems, but never when things are working well.
Trigger conditions:
- Detection quality drops: Zone-level detection quality below 60%
for >24 hours triggers helpful banner with guided diagnostics flow
- Repeated setting changes: Same qualifying settings key modified 3+
times within 60-minute sliding window triggers hint banner
- Node offline: Any node offline for >2 hours shows timeline event
with expandable troubleshooting steps
- First-time feature discovery: Brief, non-intrusive tooltips shown
once per feature
- After false positive feedback: Inline response explaining threshold
adjustments
- After successful calibration: Positive reinforcement message
showing quality improvement
Design principles:
- Reactive, not proactive: help appears only when something seems wrong
- Dismissible in one tap: never blocks UI
- Never repeats after dismissal (stored in localStorage)
- Always explains what will happen next
- Never condescending: assumes user is intelligent
All tests pass (go test ./internal/guidedtroubleshoot/... and
npm test -- --testPathPattern=troubleshoot).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add briefing dashboard adapter wiring to hub for morning briefing push
- Morning briefing provides warm summary when user first opens dashboard each day
- Content includes: sleep summary, who is home, overnight anomalies, system health, predictions, learning progress
- Briefing generated automatically and stored as daily record in briefings table
- Delivered via dashboard (card overlay on first open), push notification at configured time, or webhook
- Display modes supported: expert mode (overlay), simple mode (first card), ambient mode (fade-in text)
- Briefing scheduler generates daily briefings and sends push notifications
- API endpoints: GET/POST /api/briefing/* for managing briefings
- Go function GenerateBriefing(date, person) assembles briefing in priority order
- Sections: critical alerts → sleep → who's home → anomalies → system health → predictions → learning
- Stored as daily record in briefings table with sections_json
- Expert mode: card overlay on first open, dismissible, slides away after 10s
- Simple mode: morning card as first card in layout
- Ambient mode: text fades in on first person detection, stays for 30s
- Delivery via dashboard, push notification, or webhook
- All acceptance criteria met
Dedicated display mode for wall-mounted tablets or always-on screens.
Served at /ambient as separate lightweight route.
Implementation:
- Simplified, stylized top-down floor plan with clean lines and soft rounded corners
- People appear as softly glowing colored circles (BLE-identified) or neutral dots (unknown)
- Room labels show subtle occupancy: 'Kitchen · Alice' or 'Bedroom · Empty'
- Smooth, calm animations with interpolated positions (no jitter, no snapping)
- Canvas 2D renderer for minimal resource usage (no Three.js)
- Time-of-day awareness: morning (bright/cool), day (neutral), evening (warm/amber), night (very dim)
- Auto-dim when house empty for 30+ minutes with 'All secure' text
- Alert mode: pulsing red border, large text, action buttons for fall/security events
- Morning briefing integration: shows briefing text on first person detection
Files:
- dashboard/ambient.html - Ambient mode page
- dashboard/js/ambient.js - Ambient controller with WebSocket
- dashboard/js/ambient_renderer.js - Canvas 2D renderer with time-of-day palettes
- dashboard/js/ambient_briefing.js - Morning briefing integration
- dashboard/css/ambient.css - Comprehensive styling with time-of-day themes
Acceptance:
- Runs unattended on wall-mounted tablet for 7+ days
- Time-of-day palette transitions smoothly
- Alert mode breaks the calm appropriately
- Morning briefing displays on first detection
- Resource usage: <30 MB RAM, <5% CPU target
- Fix auto-dim timeout from 60 seconds to 30 minutes (30 * 60 * 1000ms)
- Add auth.js dependency to ambient.html for proper authentication
- Rewrite ambient.test.js to remove problematic require() statements
- Update ambient.js with proper time-of-day handling
- Enhance ambient.css with time-of-day palette themes
Ambient mode provides a simplified, always-on display for wall-mounted
tablets with Canvas 2D rendering, time-of-day awareness, auto-dim after
30min of no presence, alert mode with pulsing red border, and morning
briefing integration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Card-based mobile-first UI for non-technical users
- Room cards showing occupancy count, person names, and status color
- Activity feed with chronological event list from timeline
- Alert banner for fall detection, anomaly alerts, and system warnings
- Quick actions: arm/disarm security, re-baseline, silence alerts
- Sleep summary card showing last night's sleep data
- Toggle between simple/expert mode with localStorage preference
- Added /simple route in mothership for serving simple mode page
- Added purple color scale to tokens.css for sleep features
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add simple.html: mobile-first card-based UI without 3D scene
- Room cards show occupancy count, person names, and status color
- Activity feed displays chronological events from timeline
- Alert banner for fall detection, anomaly alerts, system warnings
- Quick actions: arm/disarm security, re-baseline, silence alerts
- Sleep summary card showing last night's sleep data
- Simple/expert mode toggle button in all views
- Mobile-responsive layout with touch-friendly interface
- Per-user default mode stored in localStorage
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Raycast against both wireframe and fill meshes for reliable detection
- Wireframe is always present even when fill has 0 opacity (zones 2+)
- Sort intersections by distance to get the closest intersection
- Fixes hover detection not working properly for multi-zone Fresnel ellipsoids
- Fixed onFresnelMouseMove to properly iterate through arrays of ellipsoids
- Fixed showFresnelTooltip to access ellipsoid data from array correctly
- Enhanced tooltip to show zone count and improved units display
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Rebuilt spaxel-sim binary with latest code
- Copied binary to mothership directory for use in integration tests
- All tests pass (go test ./... && go vet ./...)
Implemented the CSI simulator CLI tool for testing Spaxel without
hardware. The simulator connects to a running mothership via WebSocket
and streams synthetic CSI binary frames.
Features:
- Virtual nodes positioned at corners, evenly distributed
- Walker random walk with Gaussian velocity updates (σ=0.3 m/s per axis per 50ms)
- Synthetic CSI generation using propagation model (path-loss + Fresnel zones)
- Binary frame format matching ingestion/frame.go (24-byte header + n_sub*2 payload)
- RSSI calculation: clamp(-30 - path_loss_dB, -90, -30)
- BLE advertisement simulation every 5s when --ble flag is set
- Reject detection: exits non-zero on {type:'reject'} from mothership
- Per-second stats: frame counts and blob count (from GET /api/blobs poll)
CLI Interface:
spaxel-sim --mothership ws://localhost:8080/ws/node --token <token> \
--nodes 4 --walkers 1 --rate 20 --duration 60s --ble \
--seed 42 --space '6x5x2.5'
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add fetchBlobCount() function that queries the mothership's /api/blobs
endpoint and updates reportStats() to include blob count in periodic
statistics. Also updates printFinalStats() to show final blob count.
This completes the acceptance criteria for printing per-second frame
counts AND blob counts from GET /api/blobs poll.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix GetShoppingList to use proper GDOP-based accuracy estimation
instead of simplified implementation
- Fix simulation flow to run synchronously and display results
immediately instead of polling
- Update GDOP legend HTML structure with proper styling hooks
- Add shopping list container with "add node at worst spot" button
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix infinity handling in accuracy_map for GDOP overlay JSON output
- Convert average_gdop infinity to string for JSON compatibility
- Use 9999.0 sentinel value for infinity in accuracy_map array
This fixes the 'unsupported value: +Inf' error when using --gdop-overlay flag.
Both --gdop-overlay and --shopping-list now output valid JSON.
- Implements full CSI simulator CLI at cmd/sim/
- Synthetic CSI frame generation using two-ray propagation model (direct + first-order reflection)
- Walker types: random-walk, path-following, node-to-node traversal
- User-defined paths via JSON file (--path-file)
- Wall attenuation with material properties (drywall, brick, concrete, glass, metal)
- BLE advertisement simulation (--ble flag)
- Ground truth CSV output with walker positions and per-link deltaRMS
- Scenario support: fall detection, OTA, bag-on-couch
- Blob count verification via --verify flag
- Seed-based reproducibility for deterministic tests
- Full test coverage (33 tests passing)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The test was using a wall at x=10 from y=0 to y=5, which still creates
a valid reflection geometry for TX at (1,1) and RX at (3,3). The
reflection point calculation correctly finds that the reflected ray
would intersect the wall at y≈2.125, which is within the wall's bounds.
Fixed the test to use a wall that truly cannot create a valid reflection:
vertical wall at x=2 from y=10 to y=15. The reflection of TX (1,1) across
x=2 would be at (3,1). The line from (3,1) to RX (3,3) is vertical at x=3,
which never intersects the wall at x=2.
The simulator implements:
- Synthetic walkers (random walk, path-following, node-to-node)
- CSI generation with two-ray propagation model
- Wall attenuation (drywall: 3dB, brick/concrete: 10dB, glass: 2dB, metal: 20dB)
- Fresnel zone-based deltaRMS computation
- BLE simulation and CSV ground truth output
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Cleaned up unused variables in ray-based propagation model:
- Removed unused directPathLoss in computeReflectionPower
- Removed unused reflectionZ in floor/ceiling reflection functions
The propagation engine implements:
- Direct path computation (TX -> walker -> RX)
- First-order reflections (walls, floor, ceiling)
- Path loss model using log-distance
- Wall attenuation based on material type
- Fresnel zone modulation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Press space bar to place a new virtual node at camera target position
- Node is placed at intersection of camera ray with ground plane
- Position is clamped to room bounds
- Height defaults to 80% of room height or 1.5m minimum
- Virtual nodes are rendered as ghost wireframe nodes (via viz3d.js)
- Links to/from virtual nodes are dashed (via viz3d.js)
This completes the 'space + virtual node placement' feature for the
simulator, reusing the 3D editor with ghost wireframe nodes and dashed links.