Skip to content

fix(glanceable): rate-limit native updates to stop device overheating - #6323

Open
iscekic wants to merge 1 commit into
mainfrom
kwf/req-20260918-044333-77b6
Open

iscekic wants to merge 1 commit into
mainfrom
kwf/req-20260918-044333-77b6

Conversation

@iscekic

@iscekic iscekic commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • The phone no longer heats up during long runs of 5–15 remote CLI sessions, because the glanceable surfaces stop updating on every heartbeat.
  • The widget, Live Activity, and ongoing notification still show live counts, but counts-only changes may lag by up to 10 seconds.
  • Approval prompts appear and clear immediately, so the Approve control is not delayed by the update window.
  • Only the account whose session moved into or out of an approval prompt bypasses the update window; other accounts in the same batch keep the normal cadence.
  • Renaming the newest session still redraws the surface promptly.
  • A Live Activity that failed to start is retried while the counts stay stable, instead of staying hidden until the counts change.
  • A deferred counts update is retried if its refresh fails or if an approval prompt is delivered while it is queued, so the final counts are not lost.

Changelog for maintainers

  • services/notifications/src/index.ts:354 — accepted: one request-level flag exempted every scope in a multi-org batch, including scopes whose sessions never touched permission. The refresh RPC now takes approvalChangedSessionIds, and the service exempts only the scopes those ids resolve to.
  • apps/mobile/src/lib/glanceable/publisher.ts:201 — accepted: an unchanged-content renewal emitted a newer frame while a coalesced timer held an older snapshot, so the timer later republished the older revision and timestamp. The renewal now cancels the pending coalesce before emitting.
  • services/notifications/src/lib/glanceable-refresh.ts:146 — accepted: the awaited trailing build runs before the revision fence, so a concurrent refresh can deliver while it is in flight. The trailing branch now reads the delivery record and re-arms only when no newer delivery landed; delivery records carry outcome: 'delivered' | 'failed', and a record without the field predates it and counts as delivered.
  • services/session-ingest/src/ingest/metadata.test.ts:620 — accepted: the added tests moved question -> permission, which is still true through the session.status clause, so the previousStatus === 'permission' branch was unverified. A permission -> busy case now covers the clearing direction.
  • services/session-ingest/src/dos/UserConnectionDO.ts:1935 — accepted: a disconnecting CLI named a permission subagent's own id, which the server cannot resolve, so the owning org scope lost the exemption. The disconnect caller now names the owning root session id.
  • The publisher skips the native write when status, running, needsInput, needsApproval, idle, needsInputSince, and the newest title are unchanged, and the shared coalesce window rises from 1 s to 10 s; the unchanged-content renewal re-issues the Live Activity start/update at the stale-window margin instead of only republishing, so a start the sink could not raise is retried while the counts stay stable.
  • Delivery is rate-limited to one aggregate device wake per account scope per 10 s; a change inside the window is stored as a pending record and delivered by the Durable Object alarm as a trailing refresh carrying the final counts. A failed attempt still spends the window, pending records carry their write time, a trailing refresh with no authoritative snapshot re-arms the record, and the sweep folds the earliest remaining pending deadline into its next alarm. Content-free build and delivery logs (identifiers and aggregate counts only) make the one-build-per-window invariant auditable.
  • Review first the scope mapping in refreshGlanceableSessions and the trailing re-arm fence in glanceable-refresh.ts; both decide whether a device is woken.

E2E proof

Captured 2026-09-18. The appended backend re-run is the post-repair run and replaces the earlier pre-repair excerpt; the CLI check did not start and is not counted. The captures are Android; no iOS capture ran, though the request asked for both platforms. The iOS capture is skipped and pending owner verification.

[e3] No remote CLI sessions (empty tray): Agents tab shows the empty state and no live count — prior/e3.png

[e8] ux-check: move a session between question and permission; the Approve control must appear/disappear within ~1s, not the 10s window — prior/e8-shade-approve.png

[e8] ux-check: move a session between question and permission; the Approve control must appear/disappear within ~1s, not the 10s window — prior/e8-shade-question.png

[e3] No remote CLI sessions (empty tray): Agents tab shows the empty state and no live count — scripted-shard1/e3.png

Owner request

The phone gets unbearably hot during normal use, with 5 to 15 remote CLI sessions running. Confirm the cause through debug logs or profiling, then fix.

E2E proof — log excerpts

INTERNAL_API_SECRET missing; skipping glanceable aggregate delivery
 ✓ src/lib/glanceable-refresh.test.ts (7 tests) 117ms
Using secrets defined in .dev.vars
 ✓ src/lib/scheduled-action-push.test.ts (14 tests) 89ms
Using secrets defined in .dev.vars
 ✓ src/lib/notifications-service-cloud-agent.test.ts (35 tests) 62ms
Using secrets defined in .dev.vars
 ✓ src/__tests__/routes-dispatch.test.ts (7 tests) 93ms
Using secrets defined in .dev.vars
 ✓ src/lib/apns-live-activity.test.ts (11 tests) 39ms
Using secrets defined in .dev.vars
 ✓ src/lib/agent-session-notification-push.test.ts (16 tests) 61ms
Using secrets defined in .dev.vars
 ✓ src/lib/notifications-service.test.ts (15 tests) 31ms
Using secrets defined in .dev.vars
 ✓ src/__tests__/send-push-for-conversation.test.ts (6 tests) 74ms
Using secrets defined in .dev.vars
 ✓ src/lib/push-sink.test.ts (5 tests) 11ms
 ✓ src/lib/internal-dispatch-push.test.ts (24 tests) 25ms
 ✓ src/queue-consumer.test.ts (1 test) 11ms
 Test Files  17 passed (17)
      Tests  319 passed (319)
   Start at  05:31:33
   Duration  46.32s (transform 15.24s, setup 693ms, import 95.97s, tests 12.54s, environment 7ms)

@iscekic
iscekic marked this pull request as draft September 18, 2026 18:26
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from 5debca9 to 62202ed Compare September 18, 2026 19:31
@iscekic
iscekic marked this pull request as ready for review September 18, 2026 19:52
Comment thread apps/mobile/src/lib/glanceable/publisher.ts Outdated
Comment thread services/notifications/src/lib/glanceable-refresh.ts
Comment thread services/notifications/src/lib/glanceable-refresh.ts
Comment thread services/notifications/src/dos/NotificationChannelDO.ts
@kilo-code-bot

kilo-code-bot Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Executive Summary

The approval-exemption hint is a single request-level flag applied to every account scope, so a permission move on one session bypasses the rate-limit window on unrelated scopes; three lower-severity ordering and coverage gaps round out the review.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 3
Issue Details (click to expand)

WARNING

File Line Issue
services/notifications/src/index.ts 354 approvalChanged is forwarded to every resolved scope, so a permission move on one session exempts unrelated scopes from the per-scope delivery window

SUGGESTION

File Line Issue
apps/mobile/src/lib/glanceable/publisher.ts 201 Renewal emit can race a pending coalesced emit and republish an older revision/updatedAt
services/notifications/src/lib/glanceable-refresh.ts 146 Trailing null-build re-arm ignores supersession, allowing a redundant device wake after a newer delivery
services/session-ingest/src/ingest/metadata.test.ts 620 New tests do not cover the permission-clearing half of the approvalChanged expression
Files Reviewed (15 files)
  • apps/mobile/src/lib/glanceable/publisher.ts - 1 issue
  • apps/mobile/src/lib/glanceable/publisher.test.ts
  • apps/mobile/src/lib/glanceable/snapshot-transforms.ts
  • packages/app-shared/src/glanceable-agents-snapshot.ts
  • packages/notifications/src/rpc-schemas.ts
  • packages/notifications/src/rpc-schemas.test.ts
  • services/notifications/src/lib/glanceable-refresh.ts - 1 issue
  • services/notifications/src/lib/glanceable-refresh.test.ts
  • services/notifications/src/lib/glanceable-delivery.test.ts
  • services/notifications/src/dos/NotificationChannelDO.ts
  • services/notifications/src/index.ts - 1 issue
  • services/session-ingest/src/dos/UserConnectionDO.ts
  • services/session-ingest/src/dos/UserConnectionDO.test.ts
  • services/session-ingest/src/ingest/metadata.ts
  • services/session-ingest/src/ingest/metadata.test.ts - 1 issue

Fix these issues in Kilo Cloud

Previous Review Summaries (5 snapshots, latest commit fe39011)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit fe39011)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental changes re-arm a failed trailing glanceable refresh so deferred counts are not lost, and make the UserConnectionDO storage fake model its alarm; the two previously reported issues are addressed on the changed lines and no new issues were found.

Files Reviewed (3 files)
  • services/notifications/src/lib/glanceable-refresh.ts
  • services/notifications/src/lib/glanceable-refresh.test.ts
  • services/session-ingest/src/dos/UserConnectionDO.test.ts

Previous review (commit c09f32f)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
services/notifications/src/lib/glanceable-refresh.ts 319 A trailing delivery that throws drops the already-consumed pending deferral with no re-arm, so the deferred final counts can be lost.

SUGGESTION

File Line Issue
services/session-ingest/src/dos/UserConnectionDO.test.ts 655 The fake DO storage omits getAlarm, so the new deferral test throws internally and passes without verifying the alarm is armed.
Files Reviewed (15 files)
  • apps/mobile/src/lib/glanceable/publisher.ts
  • apps/mobile/src/lib/glanceable/publisher.test.ts
  • apps/mobile/src/lib/glanceable/snapshot-transforms.ts
  • packages/app-shared/src/glanceable-agents-snapshot.ts
  • packages/notifications/src/rpc-schemas.ts
  • packages/notifications/src/rpc-schemas.test.ts
  • services/notifications/src/index.ts
  • services/notifications/src/dos/NotificationChannelDO.ts
  • services/notifications/src/lib/glanceable-refresh.ts - 1 issue
  • services/notifications/src/lib/glanceable-refresh.test.ts
  • services/notifications/src/lib/glanceable-delivery.test.ts
  • services/session-ingest/src/dos/UserConnectionDO.ts
  • services/session-ingest/src/dos/UserConnectionDO.test.ts - 1 issue
  • services/session-ingest/src/ingest/metadata.ts
  • services/session-ingest/src/ingest/metadata.test.ts

Fix these issues in Kilo Cloud

Previous review (commit 5a4d8db)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • services/notifications/src/lib/glanceable-refresh.ts
  • services/notifications/src/lib/glanceable-refresh.test.ts

Previous review (commit f990f3d)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
services/notifications/src/lib/glanceable-refresh.ts 64 An approval-exempt in-window delivery can delete a counts-only deferral written while it is in flight, dropping the final counts until the next status change.
Files Reviewed (12 files)
  • apps/mobile/src/lib/glanceable/publisher.ts
  • apps/mobile/src/lib/glanceable/publisher.test.ts
  • packages/notifications/src/rpc-schemas.ts
  • packages/notifications/src/rpc-schemas.test.ts
  • services/notifications/src/index.ts
  • services/notifications/src/dos/NotificationChannelDO.ts
  • services/notifications/src/lib/glanceable-refresh.ts - 1 issue
  • services/notifications/src/lib/glanceable-refresh.test.ts
  • services/session-ingest/src/dos/UserConnectionDO.ts
  • services/session-ingest/src/dos/UserConnectionDO.test.ts
  • services/session-ingest/src/ingest/metadata.ts
  • services/session-ingest/src/ingest/metadata.test.ts

Fix these issues in Kilo Cloud

Previous review (commit 62202ed)

Status: 4 Issues Found | Recommendation: Address before merge

Executive Summary

The new same-content early return in the mobile publisher permanently stops retrying startOrUpdate (a Live Activity can stay absent), and the backend trailing-refresh drops its pending record on the production null-build path so deferred counts can be lost.

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/glanceable/publisher.ts 153 Unchanged-content early return only publishes, never startOrUpdate, so a failed/deferred Live Activity start is never retried while counts are stable.
services/notifications/src/lib/glanceable-refresh.ts 252 Pending record is deleted before the trailing refresh; production buildSnapshot returns null (no throw), so the final counts are dropped with no re-arm.
services/notifications/src/lib/glanceable-refresh.ts 60 The server-side 10 s window has no exemption for needsApproval, so on the locked/background path the Approve control can lag up to a full window.

SUGGESTION

File Line Issue
services/notifications/src/dos/NotificationChannelDO.ts 455 The glanceable deadline is captured once; a concurrent deferral during alarm()'s awaits can be overwritten by the final setAlarm, delaying the trailing delivery.
Files Reviewed (9 files)
  • apps/mobile/src/lib/glanceable/publisher.ts - 1 issue
  • apps/mobile/src/lib/glanceable/publisher.test.ts
  • apps/mobile/src/lib/glanceable/snapshot-transforms.ts
  • packages/app-shared/src/glanceable-agents-snapshot.ts
  • services/notifications/src/dos/NotificationChannelDO.ts - 1 issue
  • services/notifications/src/lib/glanceable-delivery.test.ts
  • services/notifications/src/lib/glanceable-refresh.test.ts
  • services/notifications/src/lib/glanceable-refresh.ts - 2 issues
  • services/session-ingest/src/dos/UserConnectionDO.test.ts

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic marked this pull request as draft September 18, 2026 20:16
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from ca843bd to f990f3d Compare September 18, 2026 21:36
@iscekic
iscekic marked this pull request as ready for review September 18, 2026 21:56
Comment thread services/notifications/src/lib/glanceable-refresh.ts
@iscekic
iscekic marked this pull request as draft September 18, 2026 22:04
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from f990f3d to 7a1c91e Compare September 18, 2026 22:44
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from 7a1c91e to 5a4d8db Compare September 18, 2026 22:57
@iscekic
iscekic marked this pull request as ready for review September 19, 2026 00:06
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 19, 2026
@iscekic iscekic self-assigned this Sep 19, 2026
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from 5a4d8db to c09f32f Compare September 19, 2026 23:26
Comment thread services/notifications/src/lib/glanceable-refresh.ts
Comment thread services/session-ingest/src/dos/UserConnectionDO.test.ts
Comment thread services/notifications/src/index.ts Outdated
Comment thread apps/mobile/src/lib/glanceable/publisher.ts
Comment thread services/notifications/src/lib/glanceable-refresh.ts
Comment thread services/session-ingest/src/ingest/metadata.test.ts
@iscekic
iscekic force-pushed the kwf/req-20260918-044333-77b6 branch from b48f111 to 0edfab8 Compare September 20, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant