From 662d8d7b90ff1ef1457395899bc012eef781e9f4 Mon Sep 17 00:00:00 2001 From: Matiss Jurevics Date: Wed, 11 Mar 2026 14:30:00 +0000 Subject: [PATCH] Document motion detection rollout status --- ...WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md | 32 +++ ...D_WEB_MOTION_DETECTION_EXECUTION_PROMPT.md | 40 +++ ...EB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md | 229 ++++++++++++++++++ ..._WEB_MOTION_DETECTION_VALIDATION_MATRIX.md | 34 +++ 4 files changed, 335 insertions(+) create mode 100644 docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md create mode 100644 docs/FOREGROUND_WEB_MOTION_DETECTION_EXECUTION_PROMPT.md create mode 100644 docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md create mode 100644 docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md diff --git a/docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md b/docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md new file mode 100644 index 0000000..84898a8 --- /dev/null +++ b/docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md @@ -0,0 +1,32 @@ +# Foreground Web Motion Detection Absolute Checklist + +- `MWM-001` Confirm first-release scope is web camera role only and foreground-tab only. +- `MWM-002` Add detector-related state fields to [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4). +- `MWM-003` Define default motion detector config values for low-power foreground operation. +- `MWM-004` Create a dedicated detector module under `WebApp/src/lib/app/`. +- `MWM-005` Implement low-resolution frame sampling from the existing local camera stream. +- `MWM-006` Implement grayscale conversion and normalized frame-difference scoring. +- `MWM-007` Implement score smoothing or block aggregation to reduce noise flicker. +- `MWM-008` Implement detector state machine transitions `idle`, `warming_up`, `monitoring`, `triggered`, `cooldown`. +- `MWM-009` Implement adaptive sampling so idle sampling is slower than candidate-motion sampling. +- `MWM-010` Ensure the detector starts only when the device role is `camera`, preview is ready, and detection is armed. +- `MWM-011` Ensure the detector pauses or stops on camera permission loss, preview teardown, socket disconnect, or page hide. +- `MWM-012` Add camera dashboard controls for arm/disarm and sensitivity. +- `MWM-013` Add camera dashboard status UI for detector state and live motion score. +- `MWM-014` Keep existing manual motion buttons intact and usable. +- `MWM-015` Wire automatic detector trigger to the existing `startMotion` flow with `triggeredBy: "auto_motion"`. +- `MWM-016` Prevent duplicate `startMotion` calls while a motion event is already active. +- `MWM-017` Implement minimum event duration and quiet cooldown before automatic end. +- `MWM-018` Wire automatic quiet-state completion to the existing `endMotion` flow. +- `MWM-019` Add activity-log messages for detector armed/disarmed, trigger start, trigger end, and detector pause reasons. +- `MWM-020` Add local persistence for detector settings so operator choices survive reloads. +- `MWM-021` Validate that existing client notifications still fire through the unchanged backend event routes. +- `MWM-022` Validate that existing recording behavior still works for auto-started motion events. +- `MWM-023` Add unit-level tests for detector scoring and state-machine transitions. +- `MWM-024` Add integration tests or deterministic mocks for event deduplication and cooldown handling. +- `MWM-025` Perform manual runtime validation for no-motion idle scene, real person entry, lighting flicker, and camera shake. +- `MWM-026` Measure runtime CPU/thermal behavior during a long foreground session and tune defaults if needed. +- `MWM-027` Document the foreground-only assumption and known limits in project docs. +- `MWM-028` Document recommended operator settings for lowest battery and heat. +- `MWM-029` Add rollback behavior so disabling detection immediately stops the detector loop and leaves manual controls intact. +- `MWM-030` Finalize a rollout note describing first-release non-goals such as background detection and ML classification. diff --git a/docs/FOREGROUND_WEB_MOTION_DETECTION_EXECUTION_PROMPT.md b/docs/FOREGROUND_WEB_MOTION_DETECTION_EXECUTION_PROMPT.md new file mode 100644 index 0000000..ac1bc5b --- /dev/null +++ b/docs/FOREGROUND_WEB_MOTION_DETECTION_EXECUTION_PROMPT.md @@ -0,0 +1,40 @@ +# Foreground Web Motion Detection Execution Prompt + +Implement automatic foreground-only motion detection for the web camera role using the artifacts below as the source of truth: + +- [FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md) +- [FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_ABSOLUTE_CHECKLIST.md) +- [FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md](/home/matiss/Documents/Final%20Year%20Project/docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md) + +## Delivery Rules + +- Treat the implementation plan as authoritative for architecture and sequencing. +- Complete checklist items atomically and update the validation matrix with evidence as work lands. +- Do not silently skip hidden work such as store updates, detector lifecycle cleanup, tests, docs, and runtime validation. +- Reuse the existing backend motion lifecycle before introducing any new backend motion pipeline. +- Preserve manual motion controls and existing client notification behavior. + +## Evidence Rules + +- Every completed checklist item must have at least one evidence entry in the validation matrix. +- `Code` evidence must reference the file changed. +- `Test` evidence must reference a deterministic automated or manual validation step. +- `Runtime` evidence must reference an observed app behavior, command result, or manual scenario outcome. + +## Completion Gates + +- Automatic motion detection works only for the web `camera` role. +- The detector runs only while the browser tab is in the foreground and the detector is armed. +- The detector starts and ends existing motion events automatically without duplicate starts. +- Client notifications and recordings continue to function through existing backend routes. +- Manual motion controls still work. +- Detector settings are user-visible and persisted locally. +- Tests and runtime validation cover idle scenes, real motion, flicker, and camera shake. + +## Suggested First Batch + +1. Add store fields and camera dashboard controls. +2. Add the detector module with live score reporting only. +3. Tune thresholds manually on the camera dashboard. +4. Wire automatic start/end to the existing motion event flow. +5. Add tests, docs, and validation evidence. diff --git a/docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md b/docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md new file mode 100644 index 0000000..d774842 --- /dev/null +++ b/docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md @@ -0,0 +1,229 @@ +# Foreground Web Motion Detection Implementation Plan + +## Summary + +Implement automatic motion detection for the `camera` role in the web app while the browser remains open in the foreground on a plugged-in phone. Reuse the existing backend motion event, notification, recording, and stream flows instead of introducing a new backend motion pipeline. + +## Goals + +- Detect motion automatically from the local camera preview in the web app. +- Trigger the existing motion event lifecycle with minimal backend change. +- Minimize battery and heat by using low-resolution frame analysis and adaptive sampling. +- Keep the first release heuristic and deterministic rather than ML-based. +- Make behavior observable and tunable from the camera dashboard. + +## Constraints + +- The browser tab is assumed to remain visible in the foreground. +- The initial target is the web app camera dashboard, not the Expo mobile app. +- Existing backend endpoints remain the source of truth for motion events. +- The current camera role UX in [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:31) must continue to work. +- The current motion event routes in [Backend/routes/events.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/events.ts:35) and [Backend/routes/events.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/events.ts:142) should be reused. + +## Assumptions + +- Manual motion controls remain available as an operator override. +- `triggeredBy` can distinguish manual versus automatic events without a schema change. +- Persisted per-device motion settings are desirable, but an in-memory first pass is acceptable. +- The existing recording behavior tied to stream/motion events remains the intended user experience. + +## Non-Goals + +- True background detection while the browser tab is hidden. +- ML person/pet/vehicle classification in the first release. +- Replacing the current notification or recording architecture. +- Solving appliance-grade uptime guarantees. + +## Existing Integration Points + +- Camera preview and camera dashboard actions are already hosted in [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:105). +- Local camera capture and preview lifecycle already exist in [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:233). +- Manual motion start/end already call the backend in [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:1374). +- Camera-side state is stored in [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4). + +## Strategy + +### Phase 1: Add Motion Detector State And Controls + +Add camera-side detector state to the Svelte store: + +- `motionDetectionEnabled` +- `motionDetectorStatus` such as `idle`, `warming_up`, `monitoring`, `triggered`, `cooldown` +- `motionSensitivity` +- `motionSampleIntervalMs` +- `motionTriggerConsecutiveFrames` +- `motionQuietCooldownMs` +- `motionMinimumEventMs` +- `motionScore` +- `motionDebugEnabled` + +Expose controls on the camera dashboard: + +- Arm/disarm automatic detection +- Sensitivity slider or preset selector +- Low-power mode preset +- Live debug score and current detector state + +Keep the existing manual `Simulate Motion Event` and `Stop Recording` actions for fallback. + +### Phase 2: Build A Lightweight Detector Engine + +Create a dedicated detector module, for example `WebApp/src/lib/app/motion-detector.js`, owned by the camera dashboard flow. + +Detector design: + +- Read from the existing `localCameraStream` +- Draw frames into an offscreen or hidden canvas +- Downsample aggressively to about `160x90` or `192x108` +- Convert to grayscale +- Compare the current frame against the previous smoothed frame +- Compute a normalized motion score such as changed-pixel ratio or block-delta score +- Ignore tiny isolated noise with thresholding and optional block aggregation + +Battery and heat controls: + +- Default sampling at `1 fps` +- Burst to `4-6 fps` only after suspicious motion begins +- Return to low sampling after cooldown +- Skip work if preview is not ready, detector is disarmed, or document visibility changes +- Avoid full-resolution processing and avoid network uploads during detection itself + +### Phase 3: Add Event State Machine And Backend Reuse + +Implement a camera-side state machine: + +- `idle` -> `monitoring` +- `monitoring` -> `candidate_motion` +- `candidate_motion` -> `triggered` +- `triggered` -> `cooldown` +- `cooldown` -> `monitoring` + +Trigger rules: + +- Require `N` consecutive high-motion frames before starting an event +- Call the existing backend motion start endpoint once +- Set `triggeredBy` to `auto_motion` +- Hold the event open for at least `motionMinimumEventMs` +- Only end after the score stays below threshold for `motionQuietCooldownMs` + +This keeps backend changes minimal because the existing event lifecycle already fans out realtime alerts and push notifications. + +### Phase 4: Make Recording Behavior Predictable + +The detector should not record constantly. + +Recommended behavior: + +- Motion detection itself only analyzes low-res frames locally +- When automatic motion is confirmed, call the existing start-motion flow +- Continue using the current recording logic already associated with motion and streaming +- End the motion event only after quiet cooldown, not on every instantaneous dip + +This avoids repeated start/stop loops that waste device resources. + +### Phase 5: Add Persistence For Operator Settings + +Initial implementation can use local storage on the web app for speed. + +Second step: + +- Add motion settings persistence per camera device +- Store settings either in `devices.metadata` if introduced later, or in a new `device_motion_settings` table +- Load persisted settings on device registration or camera dashboard open + +Suggested settings: + +- Enabled/armed +- Sensitivity +- Sample interval +- Quiet cooldown +- Minimum event duration +- Optional region of interest + +### Phase 6: Observability And Debugging + +Add operator-visible debug surfaces: + +- Current motion score +- Detector state +- Last trigger time +- Count of suppressed candidate triggers + +Add activity log entries for: + +- Detector armed/disarmed +- Detector warmed up +- Automatic motion started +- Automatic motion ended +- Detector paused because preview or socket is unavailable + +### Phase 7: Test And Tune + +Testing should cover: + +- Low-motion idle scenes +- Moderate lighting flicker +- Real person entry into frame +- Camera shake false positives +- Reconnection behavior +- Event deduplication + +Tuning targets: + +- Low false positive rate in static indoor scenes +- Trigger latency below about `2 seconds` +- CPU usage low enough to avoid obvious thermal throttling during foreground operation + +## File-Level Change Plan + +Primary files: + +- [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:4) +- [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:233) +- [WebApp/src/routes/camera/+page.svelte](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/routes/camera/+page.svelte:105) + +Likely new files: + +- `WebApp/src/lib/app/motion-detector.js` +- `WebApp/src/lib/app/motion-detector.test.js` or equivalent + +Optional later backend files: + +- [Backend/db/schema.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/db/schema.ts:14) +- [Backend/routes/devices.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/devices.ts:41) + +## Risk Controls + +- Use hysteresis so one threshold starts motion and a lower threshold ends it. +- Require consecutive-frame confirmation before starting events. +- Pause detection when preview, permission, or socket connectivity is unavailable. +- Keep all frame processing local and low resolution. +- Keep manual controls available during rollout. +- Ship with debug mode so threshold tuning is possible without code changes. + +## Recommended Operator Settings + +- Start with the `Balanced` profile on a plugged-in phone. +- Use `Low Power` if the phone runs warm or the scene is mostly static. +- Keep the browser tab visible and the camera dashboard open while detection is armed. +- Leave debug mode off during normal operation and enable it only while tuning thresholds. +- Prefer a stable camera mount and a consistent indoor lighting setup to reduce false positives. + +## Acceptance Criteria + +- A camera-role web device can arm automatic motion detection from the camera dashboard. +- When visible motion enters frame, the web app starts one backend motion event without duplicate starts. +- Linked clients receive the same notifications they currently receive for manual motion events. +- Motion events remain open through continuous motion and close only after quiet cooldown. +- The detector does not continuously upload frames or full video for analysis. +- Manual motion controls continue to work. +- Detector state survives normal page usage and fails safely on disconnect or permission loss. + +## Recommended Delivery Order + +1. Add store state and camera dashboard controls. +2. Add local detector engine with score reporting only, no event triggering. +3. Tune thresholds against manual test scenes. +4. Wire score transitions to automatic event start/end. +5. Add persistence for detector settings. +6. Add tests, docs, and rollout notes. diff --git a/docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md b/docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md new file mode 100644 index 0000000..388bf8b --- /dev/null +++ b/docs/FOREGROUND_WEB_MOTION_DETECTION_VALIDATION_MATRIX.md @@ -0,0 +1,34 @@ +# Foreground Web Motion Detection Validation Matrix + +| Row ID | Checklist Item | Status | Code | Test | Runtime | +| --- | --- | --- | --- | --- | --- | +| `VM-MWM-001` | Confirm first-release scope is web camera role only and foreground-tab only | done | `WebApp/src/lib/app/controller.js` `shouldRunMotionDetector`; `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Constraints/Non-Goals | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-002` | Add detector-related state fields to store | done | `WebApp/src/lib/app/store.js` `createInitialState`; `WebApp/src/lib/app/controller.js` `getDefaultMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-003` | Define default detector config values | done | `WebApp/src/lib/app/controller.js` `MOTION_DETECTION_PROFILES`, `buildMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-004` | Create dedicated detector module | done | `WebApp/src/lib/app/motion-detector.js` `createMotionDetector` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-005` | Implement low-resolution frame sampling | done | `WebApp/src/lib/app/motion-detector.js` `DEFAULT_FRAME_WIDTH`, `DEFAULT_FRAME_HEIGHT`, `analyzeFrame` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-006` | Implement grayscale conversion and frame-difference scoring | done | `WebApp/src/lib/app/motion-detector.js` `computeLuma`, `computeChangedPixelRatio` | `src/lib/app/motion-detector.spec.js` `computes grayscale luminance...`, `reports the ratio...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-007` | Implement score smoothing or block aggregation | done | `WebApp/src/lib/app/motion-detector.js` `DEFAULT_SMOOTHING_FACTOR`, `analyzeFrame` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-008` | Implement detector state machine transitions | done | `WebApp/src/lib/app/motion-detector.js` `createMotionMachineSnapshot`, `applyMotionStateMachine` | `src/lib/app/motion-detector.spec.js` `requires consecutive high-motion frames...`, `holds motion until minimum duration...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-009` | Implement adaptive sampling | done | `WebApp/src/lib/app/motion-detector.js` `tick`; `WebApp/src/lib/app/controller.js` `MOTION_DETECTION_PROFILES` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-010` | Start detector only when camera role, preview, and armed state are valid | done | `WebApp/src/lib/app/controller.js` `shouldRunMotionDetector`, `applyMotionDetectionReadiness` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-011` | Pause detector on permission loss, preview teardown, disconnect, or page hide | done | `WebApp/src/lib/app/controller.js` `getMotionDetectionPauseReason`, `applyMotionDetectionReadiness`, `onVisibilityChange` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-012` | Add camera dashboard arm/disarm and sensitivity controls | done | `WebApp/src/routes/camera/+page.svelte` Automatic Detection controls; `WebApp/src/lib/app/controller.js` `setMotionDetectionEnabled`, `setMotionDetectionProfile` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-013` | Add camera dashboard detector status and score UI | done | `WebApp/src/routes/camera/+page.svelte` Detector State/Motion Score cards | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-014` | Preserve manual motion controls | done | `WebApp/src/routes/camera/+page.svelte` manual buttons; `WebApp/src/lib/app/controller.js` `actions.startMotion`, `actions.endMotion` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-015` | Trigger existing start-motion flow with `auto_motion` | done | `WebApp/src/lib/app/controller.js` `getMotionStartPayload`, `startMotionEvent`, `syncAutoMotionLifecycle`; `WebApp/src/lib/app/api.js` `events.startMotion` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-016` | Prevent duplicate automatic motion starts | done | `WebApp/src/lib/app/controller.js` `startMotionEvent`, `syncAutoMotionLifecycle`, `autoMotionTransitionInFlight` | `src/lib/app/motion-detector.spec.js` `requires consecutive high-motion frames...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-017` | Implement minimum event duration and quiet cooldown | done | `WebApp/src/lib/app/motion-detector.js` `applyMotionStateMachine`; `WebApp/src/lib/app/controller.js` `syncAutoMotionLifecycle` | `src/lib/app/motion-detector.spec.js` `holds motion until minimum duration...` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-018` | Wire quiet-state completion to existing end-motion flow | done | `WebApp/src/lib/app/controller.js` `endMotionEvent`, `syncAutoMotionLifecycle`, `applyMotionDetectionReadiness` | `src/lib/app/motion-detector.spec.js` `holds motion until minimum duration...` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-019` | Add activity-log messages for detector lifecycle | done | `WebApp/src/lib/app/controller.js` `addActivity` calls in `applyMotionDetectionReadiness`, `setMotionDetectionEnabled`, `startMotionEvent`, `endMotionEvent` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-020` | Add local persistence for detector settings | done | `WebApp/src/lib/app/controller.js` `loadMotionDetectionSettings`, `persistMotionDetectionSettings`, `updateMotionDetectionState` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-021` | Validate existing client notifications still work | pending | Existing backend fan-out remains unchanged in `Backend/routes/events.ts` | | Runtime validation still required with linked client devices | +| `VM-MWM-022` | Validate recording behavior still works for auto-started events | pending | Existing recording paths remain in `WebApp/src/lib/app/controller.js` `startLocalRecording`, `endMotionEvent`, `uploadStandaloneMotionRecording` | | Runtime validation still required with an actual auto-triggered event | +| `VM-MWM-023` | Add unit tests for scoring and state-machine transitions | done | `WebApp/src/lib/app/motion-detector.js` exported helpers; `WebApp/src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` | `bun run test -- src/lib/app/motion-detector.spec.js` -> `4 passed` | +| `VM-MWM-024` | Add integration tests or deterministic mocks for cooldown and dedupe | in_progress | `WebApp/src/lib/app/motion-detector.spec.js` covers deterministic cooldown and trigger gating; controller dedupe still untested | `bun run test -- src/lib/app/motion-detector.spec.js` | Additional controller-level mock coverage still needed | +| `VM-MWM-025` | Perform manual validation for idle, real motion, flicker, and camera shake | pending | | | | +| `VM-MWM-026` | Measure runtime CPU and thermal behavior during long foreground session | pending | | | | +| `VM-MWM-027` | Document foreground-only assumption and limits | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Constraints/Non-Goals/Acceptance Criteria | | Doc updated in repo | +| `VM-MWM-028` | Document recommended low-battery and low-heat settings | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Battery and heat controls; Recommended Operator Settings | | Doc updated in repo | +| `VM-MWM-029` | Add immediate rollback behavior when detection is disabled | done | `WebApp/src/lib/app/controller.js` `setMotionDetectionEnabled`, `applyMotionDetectionReadiness`, `endMotionEvent` | `bun run check` | `bun run check` -> `svelte-check found 0 errors and 0 warnings` | +| `VM-MWM-030` | Publish rollout note for first-release non-goals | done | `docs/FOREGROUND_WEB_MOTION_DETECTION_IMPLEMENTATION_PLAN.md` Non-Goals | | Doc updated in repo |