Skip to content

fix(mobile): sync app badge with needs-input count - #5873

Draft
iscekic wants to merge 3 commits into
mainfrom
kwf/deliver-the-work-described-b-fbf8
Draft

fix(mobile): sync app badge with needs-input count#5873
iscekic wants to merge 3 commits into
mainfrom
kwf/deliver-the-work-described-b-fbf8

Conversation

@iscekic

@iscekic iscekic commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Not verified. kwf reopened this section on 2026-09-05: the section reached 8 device rounds without a passing verdict
The proof below came from an earlier round and can be stale. Do not review until this note is gone.

Changelog for users

  • The app badge now matches the number of sessions that need input.
  • The app badge updates after foreground refreshes, background refreshes, and glanceable push updates.
  • A zero needs-input count clears the app badge.
  • Regular chat pushes no longer change the app badge independently.

Changelog for maintainers

  • The glanceable snapshot now owns all native app badge writes.
  • Glanceable push messages carry the needs-input count and the scope collapse identifier.
  • Ordinary push messages no longer carry a badge value.
  • Badge writes run in order and report failures to Sentry.
  • The change removes the badge freshness epoch and hydration reconciliation logic.

Changes by area

Mobile glanceable state

The app registers a badge sink that publishes the current needs-input count. The notification handler disables automatic badge changes.

Mobile unread state

Mark-read and badge hydration flows no longer write the native badge. Mark-read still updates the badge cache and invalidates the query.

Push delivery

Glanceable pushes send the latest needs-input count and collapse by scope. Ordinary notification pushes still maintain unread buckets without setting the badge.

Test coverage

Tests cover count updates, zero states, stale snapshots, ordered writes, failed writes, push handling, background delivery, and retry behavior.

E2E proof

Driver checks: per-slice checks passed
Section `backend` verification output:
backend: testing notifications
  notifications passed
Section `mobile-app` verification output:
mobile: gates cached for edf03a87c8728f7f091b323e996bb69076ec764f (skipped)
mobile-device: 3 shard(s) over 3 device(s): CEB47290-FE68-4B66-9A70-98C3F21E4FFB 1A7A48C9-C414-4FAA-94B5-9EEFBC297573 F9258B24-EB1E-469F-A38D-2B873946DAF8
mobile-device: login probe passed on 3 device(s); app signed in
mobile-device: verifier passed
mobile-device: spot check clean

The recording shows the live needs-input flow; the app badge must follow each glanceable state.

e21.mp4.trim.mp4

The launcher screenshot shows the live badge test; the badge must match the needs-input state.

e2e-mobile-app/e1-launcher.png

The first badge screenshot shows a session that needs input; the badge must show that count.

e2e-mobile-app/e1-badge.png

The later badge screenshot shows an updated needs-input state; the badge must follow the new count.

e2e-mobile-app/e9-badge.png

The clear screenshot shows a session that no longer needs input; the app badge must clear.

e2e-mobile-app/e10-after-clear.png

The additional badge screenshot shows another needs-input state; the badge must match that state.

e2e-mobile-app/e4-badge.png

Notes

  • Pre-existing defect: The Test Account row and email are clipped under the tab bar.
  • Pre-existing defect: The globe icon is clipped and overlaps the Refreshing banner.

Pre-existing UX defects observed (not changed here)

  • e10-profile.png — [pre-existing] Test Account row and email clipped under the tab bar.
  • login-shots/01-login-request-code.png — [pre-existing] Globe icon clipped at the top-right, overlapping the Refreshing banner.
  • login-shots/01-login-request-code.png — default-looking blue “Refreshing…” bar overlaps and clips the Kilo logo on the verify-code screen

e14-reconnected-badge-clear

e12-after-signout-badge-clear

e18-count-0

@kilo-code-bot

kilo-code-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (13 files)
  • apps/mobile/src/components/kilo-chat/hooks/mark-read-operation.ts
  • apps/mobile/src/components/kilo-chat/hooks/use-mark-read.ts
  • apps/mobile/src/components/kilo-chat/mark-read-state.test.ts
  • apps/mobile/src/lib/badge-freshness.ts
  • apps/mobile/src/lib/badge-hydration.ts
  • apps/mobile/src/lib/hooks/use-unread-counts-invalidation.ts
  • apps/mobile/src/lib/hooks/use-unread-counts.ts
  • apps/mobile/src/lib/notifications.test.ts
  • apps/mobile/src/lib/notifications.ts
  • services/notifications/src/__tests__/dispatch-push.test.ts
  • services/notifications/src/dos/NotificationChannelDO.ts
  • services/notifications/src/lib/glanceable-delivery.test.ts
  • services/notifications/src/lib/glanceable-delivery.ts

Reviewed by grok-4.6 · Input: 230.5K · Output: 15.3K · Cached: 478.6K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 4, 2026
@iscekic
iscekic requested a review from eshurakov September 4, 2026 11:06
@iscekic
iscekic marked this pull request as draft September 4, 2026 11:39
@iscekic

iscekic commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Moved back to draft: the e2e proof in the description is not valid.

The device verifier passed seven badge scenarios and wrote notes such as "the launcher shows badge 1", but the screenshots it attached show the Kilo icon with no badge. A pixel probe over the same files confirms it: e1-badge.png, e4-badge.png and e12-badge.png carry no launcher badge, so the badge behaviour in this PR is unproven.

Two causes, both fixed in the workflow:

  • The iOS simulator had no notification authorization, so the operating system rejected every badge write. Every device now gets the permission pre-seeded before a flow runs.
  • Nothing checked a claim against its capture. Every passing scenario is now audited against the image it cites, deterministically where a script can read the state, and by a cheap vision pass otherwise. A claim the capture does not support fails the round instead of shipping.

Verification is running again. I will restore the description with real proof, or report what does not work.

@iscekic iscekic removed the human-ready The PR is ready for human review. label Sep 4, 2026
@iscekic
iscekic removed the request for review from eshurakov September 4, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant