- Adjust zoomSpeed from 1.0 to 0.6 for finer pinch zoom control on touch devices
- Add custom three-finger pan implementation since OrbitControls doesn't natively support it
- Three-finger drag now pans the camera, separating pan from pinch-zoom gesture
- Two-finger gesture changed from DOLLY_PAN to DOLLY_ROTATE for better gesture separation
- Add touch-action: none to canvas elements in expert.css and ambient.css
to prevent passive event listener warnings on iOS Safari
- Add user-scalable=no and maximum-scale=1.0 to viewport meta tags
in ambient.html and simple.html to prevent double-tap zoom
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CSS environment variables for safe-area-inset to prevent content
overlap with notch/home indicator on iOS devices.
Changes:
- expert.css: Add safe area support to body, scene container, and
simple-quick-actions (hamburger menu) navigation
- quick-actions.css: Add safe area support to context menu and
follow-mode-indicator
- panels.css: Add safe area support to toast-container
- troubleshoot.css: Add safe area support to spaxel-dismiss-all
The viewport-fit=cover meta tag was already present in index.html.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent touch events on modal panels and their backdrop from
propagating to the canvas by adding event.stopPropagation() on
panel touch listeners.
This matches the existing behavior for sidebar panels and prevents
OrbitControls from responding to touches on modal overlays.
Acceptance Criteria:
- Touch events on modal panels do not propagate to the canvas
(event.stopPropagation() on modal and backdrop touch listeners)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cap devicePixelRatio at 2.0 on screens < 1024px width
- Disable MSAA antialiasing on mobile devices
- Disable shadow maps on mobile devices
- Add frame rate capping at 30fps for struggling mobile devices
- Auto-detect low FPS and adjust frame rate accordingly
- Panel close buttons: expanded from 32x32px to 44x44px
- Slider controls: expanded drag targets to 44px height with 32px thumb
- Toggle switches: expanded to 44px minimum height
- Checkboxes: expanded touch area with pseudo-element to 44x44px
- Context menu items: minimum 44px height
- Link list entries: minimum 44px height
- All buttons: minimum 44x44px touch targets
- Small buttons use expanded padding to maintain appearance while meeting 44px requirement
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add expert.css for expert mode specific styles
- Improve mobile orientation change handling with visualViewport API support
- Add iOS Safari visual viewport resize handling for better mobile experience
- Add getViewportDimensions() function preferring visualViewport API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement transform-based slide-in animation with overlay backdrop for screens < 1024px:
- Hamburger button (44x44px touch target) in header
- Slide-in menu with translateX(0) animation (200ms ease-out)
- Semi-transparent overlay backdrop that closes on tap
- Menu contains: Node List, Link List, Presence Panel, Timeline, Devices
- Active tab opens first (last-used panel persisted to localStorage)
- Close button (X, 44px) in top-right
- Escape key closes menu
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement single non-blocking notifications when features become available.
Events:
- DiurnalBaselineActivated (7 days)
- FirstSleepSessionComplete
- WeightUpdateApproved
- AutomationFirstFired
- PredictionModelReady (7 days per person)
Each notification is keyed by unique event ID in SQLite (feature_notifications table).
Never fires twice. Dismissed by tapping. Respects quiet hours.
Files:
- mothership/internal/help/notifier.go: Notifier manages one-time feature notifications
- mothership/internal/help/notifier_test.go: Tests for notifier
- mothership/internal/help/monitor.go: FeatureMonitor checks for feature availability
- mothership/internal/help/monitor_test.go: Tests for monitor
- mothership/cmd/mothership/main.go: Integration with mothership
- mothership/internal/db/migrations.go: Add migration_015 for feature_notifications table
Acceptance:
- Each notification fires exactly once per feature
- Plain language messages
- Respects quiet hours
- SQLite persistence prevents duplicates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The help system was already fully implemented with:
- 74 help articles across 8 categories (Basics, Features, Setup, Advanced, Interface, Troubleshooting, Maintenance, Integration)
- Fuzzy search functionality matching the command palette
- Keyboard shortcut (Ctrl+?) to open help overlay
- Category filtering and action links to relevant dashboard sections
This commit fixes the addHelpButton() function to work with the existing
HTML button (id="help-btn") instead of trying to add a duplicate button.
Also removes duplicate CSS since styles are already in index.html.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add '?' button in expert mode status bar that opens help overlay
- Search input with fuzzy search (same algorithm as command palette)
- 43 help articles covering major features (sensing links, Fresnel zones,
detection quality, presence prediction, fall detection, etc.)
- Articles stored as static JSON (dashboard/help_articles.json)
- No server round-trip - loads articles client-side
- Category filter buttons for easy navigation
- Keyboard shortcut: Ctrl+? to open help overlay
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add '?' button in status bar that opens help overlay
- Fuzzy search across 37 help articles covering major features
- Sample articles include: sensing links, detection quality, presence prediction, Fresnel zone
- Articles stored as static JSON (dashboard/help_articles.json)
- No server round-trip - all client-side
- Keyboard shortcut: Ctrl+? / Cmd+?
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detects when user changes same config setting 3+ times within 24 hours.
Shows non-intrusive prompt offering help with guided calibration flow.
Guided calibration features:
- Test for false positives (walk around room)
- Test for missed motion (sit still)
- Suggest optimal value based on diurnal baseline SNR and link health
- Apply suggested value button
Files:
- dashboard/js/proactive.js: Complete implementation with localStorage tracking
Acceptance:
- Help prompt fires after 3+ changes in 24h
- Calibration flow tests both directions
- Suggests value based on system data
- Apply button works
- Add renderFeedbackExplanation() function to display detailed explanations
- Include contributing link name, threshold exceed ratio, and timestamp
- Add diagnostic info (root cause and advice) when available
- Add expandable UI with toggle arrow
- Add CSS styles for explanation section
- Show correction note about system learning from feedback
When user marks detection as FALSE_POSITIVE, show explanation:
'The system detected motion here because: [link]'s signal exceeded
threshold by Nx at [time]. Could be caused by: [root cause or
'ambient RF interference']. We've noted this and will apply a correction.'
Files: dashboard/js/feedback.js
Acceptance: explanation shown after any FALSE_POSITIVE feedback;
contains contributing link name; shows diagnostic result or default message.
- Add dashboard/js/proactive.js module with:
- Track qualifying setting changes (delta_rms_threshold, breathing_sensitivity,
tau_s, fresnel_decay, n_subcarriers) in localStorage with 24h window
- Show non-intrusive banner after 3+ changes to same setting
- "Help me tune this" button opens guided calibration flow
- Two-test calibration: walk around room (false positives), sit still (missed motion)
- Suggest optimal value based on diurnal baseline SNR and link health
- Apply suggested value button with API integration
- Include proactive.js in dashboard/index.html
- Integrate with settings-panel.js to track setting changes on save
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect when a user changes the same configuration setting more than 3
times within 24 hours and show a non-intrusive prompt offering help.
Features:
- Track qualifying setting changes (delta_rms_threshold, breathing_sensitivity,
tau_s, fresnel_decay, n_subcarriers) in localStorage
- Non-intrusive help prompt with "Help me tune this" button
- Guided calibration flow with:
- False positive test: walk around room for 15 seconds
- Missed motion test: sit still for 10 seconds
- Suggest optimal value based on diurnal baseline SNR and link health
- Apply suggested value button
- Full modal UI with progress indicators and countdown timers
- Integration with settings-panel.js for automatic tracking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added /ambient route serving ambient.html for wall-mounted tablet display
- Canvas 2D renderer at 2Hz with lerp interpolation for smooth person movement
- Time-of-day palette with 30-minute transitions (morning/day/evening/night)
- Auto-dim: reduces brightness to 40% after 60s of no presence
- Alert mode: pulsing red background for fall/security alerts
- Morning briefing overlay: 15-second overlay on first detection after 6am
- Unified alerts API for fall, anomaly, and node_offline events
- Jest test setup mocking Canvas 2D context for jsdom
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The import statement had incorrect syntax with the alias before
the package path. Fixed to standard Go import format.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix SimulateCSIData to accept []*Walker instead of []*SimWalker
- Remove unused imports (path/filepath, time) from virtual_state_test.go
- Fix assignment mismatch for CreateVirtualNode error handling
- Fix deadlock in VirtualNodeStore by using saveLocked() when mutex is held
- Refactor CreateAPNode to avoid race condition with state modification
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implemented comprehensive home automation integration with MQTT support for
Home Assistant auto-discovery and a system-wide webhook for delivering all
Spaxel events.
MQTT Client (mothership/internal/mqtt/client.go):
- Extended MQTT client with proper Home Assistant auto-discovery payloads
- Added support for person presence binary sensors with device discovery
- Added zone occupancy sensors (count + binary occupied sensors)
- Added fall detection binary sensor with safety device class
- Added system health and system mode (select) entities
- Implemented retained message support for presence and occupancy states
- Added Last Will and Testament for availability topic
- Added exponential backoff reconnection (5s to 2min cap)
- Added discovery config cleanup (empty payload) on entity deletion
MQTT Event Publisher (mothership/internal/mqtt/publisher.go):
- Subscribes to internal event bus and publishes relevant events to MQTT
- Publishes zone entry/exit events updating person presence
- Publishes fall detection events with person/zone/timestamp info
- Publishes periodic system health updates (node count, quality, mode)
- Provides zone and person mapping for proper entity naming
System Webhook Integration (mothership/internal/webhook/publisher.go):
- System-wide webhook delivering ALL spaxel events to configured URL
- Event payload includes event_type, timestamp, zone, person, blob_id, severity
- Includes X-Spaxel-Event header with event type for routing
- Implements retry policy (one retry after 30s on 5xx errors)
- Supports concurrent event publishing with goroutine safety
- Provides TestWebhook method for configuration verification
Integration Settings API (mothership/internal/api/integrations.go):
- GET/POST /api/settings/integration for MQTT and webhook configuration
- MQTT settings: broker URL, username, password, TLS, discovery prefix
- Webhook settings: URL, enabled flag
- POST /api/settings/integration/test to test connections
- Returns connection status for MQTT (connected boolean)
- Validates URL formats and required fields
Tests:
- mothership/internal/mqtt/client_test.go: MQTT client tests including
* Client creation with validation
* Home Assistant discovery config format verification
* MQTT topic generation and payload format validation
* Retained message behavior tests
* Broker URL parsing tests
- mothership/internal/webhook/publisher_test.go: Webhook tests including
* Publisher creation and config updates
* Event publishing with schema validation
* Retry on 5xx server errors
* Concurrent event publishing safety
* All event type coverage
* Test webhook delivery
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove duplicate type declarations from session.go (Space, Wall,
wallAttenuationDB, Vector3, Walker, WalkerType) — space.go and
walker.go contain the newer, more complete versions
- Update session.go to use new type names: WalkerTypeRandomWalk,
WalkerTypePathFollow, WalkerTypeNodeToNode; use Space.Bounds()
instead of .Width/.Depth; use Point instead of Vector3
- Merge ShoppingList structs: remove duplicate from gdop.go, add
OptimalPositions []Point to the canonical struct in accuracy.go
- Fix unused variables: minZ/maxZ (accuracy.go), z (accuracy.go),
nodeType (node.go), maxZ (walker.go), noise (propagation.go),
lastHealthTime and angle (cmd/sim/main.go), id (virtual_state.go)
- Fix BoundingBox field capitalization in virtual_state.go
- Fix virtualMAC to hash string nodeID to uint32 before bit-shifting
- Fix mrand alias usage in propagation.go (rand -> mrand)
- Fix PhaseAtSubcarrier capitalization in physics.go
- Fix WalkerTypePath/WalkerTypeRandom references in engine.go/handler.go
- Rename Walker to SimWalker in cmd/sim/walker.go to avoid conflict
with main.go's local Walker type
- Remove 3 duplicate OUI map keys (0x0001C8, 0x080030 ×2)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ntfy.sh delivery client with HTTP POST to custom topics
- Supports self-hosted URLs via SetURL()
- Authentication via Bearer token
- Priority levels: urgent/high/default/low/min
- PNG image attachment via base64 data URL
- Graceful error handling with logging
- Comprehensive table-driven tests
- Add Pushover delivery client with multipart form uploads
- App token and user key authentication
- Priority levels -2 to 2 with emergency retry/expire
- PNG image attachment support
- Device targeting, sound customization
- Full test coverage
- Add Webhook delivery client with JSON payloads
- Configurable HTTP method and custom headers
- Rich payload structure for all event types
- Helper functions for common payloads (fall, zone, anomaly)
- PNG image attachment via base64
- Extend NotificationManager tests with batching scenarios
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a 300x300 PNG floor-plan renderer using github.com/fogleman/gg:
- Room outlines (white rectangles on dark background)
- Zone fills (semi-transparent colored at 20% opacity)
- Zone labels (white text at centroid)
- Node positions (white dots)
- Person blobs (colored circles, diameter 10-20px based on confidence)
- Name labels above blobs
- Portal planes (thin purple lines #a855f7)
- Event highlight zone (brighter fill with white border)
Includes unit tests that verify pixel colors at known positions and
benchmark for performance validation (target: <200ms).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>