Files
boss/docs/superpowers/plans/2026-04-10-android-realtime-noise-reduction.md
2026-04-10 13:25:05 +08:00

4.7 KiB

Android Realtime Noise Reduction Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Reduce Android realtime stutter by suppressing heartbeat-only conversation refresh events and avoiding full reloads from initial SSE context snapshots.

Architecture: Keep the existing SSE endpoint and Android BossRealtimeClient. Narrow event production in upsertDeviceHeartbeat and narrow Android root-page event consumption in MainActivity.

Tech Stack: Next.js App Router backend, TypeScript node:test, Android Java native client, Server-Sent Events.


Task 1: Lock Heartbeat Event Contract

Files:

  • Create: tests/device-heartbeat-event-noise.test.ts

  • Modify: src/lib/boss-data.ts

  • Step 1: Write the failing unchanged-heartbeat test

assert.deepEqual(events.map((event) => event.event), ["devices.updated"]);
  • Step 2: Run the test and verify it fails

Run: npx tsx --test tests/device-heartbeat-event-noise.test.ts

Expected: unchanged heartbeat currently emits both devices.updated and conversation.updated.

  • Step 3: Suppress unchanged heartbeat conversation refreshes

Track whether heartbeat import/candidate state actually changes the conversation drawer. Always publish devices.updated; publish conversation.updated only when the drawer changes.

  • Step 4: Run the focused test and verify it passes

Run: npx tsx --test tests/device-heartbeat-event-noise.test.ts

Expected: unchanged heartbeat emits only devices.updated.

Task 2: Keep Import Changes Visible

Files:

  • Modify: tests/device-heartbeat-event-noise.test.ts

  • Modify: src/lib/boss-data.ts

  • Step 1: Write the changed-candidates test

assert.deepEqual(
  events.map((event) => [event.event, event.payload.deviceId, event.payload.note]),
  [
    ["devices.updated", "noise-device-b", undefined],
    ["conversation.updated", "noise-device-b", "device_import.updated"],
  ],
);
  • Step 2: Run the test and verify it fails

Run: npx tsx --test tests/device-heartbeat-event-noise.test.ts

Expected: the event exists before the fix but is too broad and lacks the device_import.updated marker.

  • Step 3: Publish a marked conversation event only for import changes

Use note: "device_import.updated" on the conditional conversation.updated heartbeat event.

  • Step 4: Run the focused test and verify it passes

Run: npx tsx --test tests/device-heartbeat-event-noise.test.ts

Expected: changed candidates publish one marked conversation refresh event.

Task 3: Avoid Android Initial Snapshot Full Reloads

Files:

  • Create: tests/android-root-realtime-noise.test.ts

  • Modify: android/app/src/main/java/com/hyzq/boss/MainActivity.java

  • Step 1: Write the failing Android static test

assert.doesNotMatch(
  source,
  /"conversation\.context_indicator\.updated"[\s\S]{0,120}return true;/,
);
  • Step 2: Run the test and verify it fails

Run: npx tsx --test tests/android-root-realtime-noise.test.ts

Expected: MainActivity currently returns true for the context snapshot event.

  • Step 3: Ignore context snapshot as a full reload trigger

Change the context snapshot branch to return false in shouldRefreshConversationsTab.

  • Step 4: Run the focused test and verify it passes

Run: npx tsx --test tests/android-root-realtime-noise.test.ts

Expected: Android root no longer treats initial snapshot events as full reload triggers.

Task 4: Verify And Ship

Files:

  • Verify: src/lib/boss-data.ts

  • Verify: android/app/src/main/java/com/hyzq/boss/MainActivity.java

  • Verify: tests/device-heartbeat-event-noise.test.ts

  • Verify: tests/android-root-realtime-noise.test.ts

  • Step 1: Run realtime and device regression tests

Run: npx tsx --test tests/device-heartbeat-event-noise.test.ts tests/android-root-realtime-noise.test.ts tests/device-gui-cli-capabilities.test.ts tests/device-execution-conflict.test.ts tests/conversation-home-items.test.ts tests/realtime-refresh-utils.test.ts tests/project-scoped-realtime-refresh.test.ts tests/android-folder-realtime-refresh.test.ts

Expected: all selected tests pass.

  • Step 2: Run project gates

Run: npm run lint

Expected: lint exits 0.

Run: npm run build

Expected: production build exits 0.

  • Step 3: Build and install Android release APK

Run: cd android && ./gradlew assembleRelease

Expected: release APK builds successfully.

Run: adb -s <wireless-device-id> install -r android/app/build/outputs/apk/release/app-release.apk

Expected: install returns Success.