Skip to content

fix(mobile): confirm connectivity and expose history liveness - #5677

Merged
iscekic merged 8 commits into
mobile-ux-ad6d-s2from
mobile-ux-ad6d-s3
Sep 1, 2026
Merged

fix(mobile): confirm connectivity and expose history liveness#5677
iscekic merged 8 commits into
mobile-ux-ad6d-s2from
mobile-ux-ad6d-s3

Conversation

@iscekic

@iscekic iscekic commented Aug 28, 2026

Copy link
Copy Markdown
Contributor
  • The app confirms a connection failure before it shows the offline warning, so a reachable service can prevent a false warning.
  • Security Agent settings retain previously loaded information during connection problems and provide Retry progress for personal and organization accounts.
  • History and search results mark running sessions as live while continuing to show their cost and time.
  • In session lists, screen readers announce live status after the title, unless the session needs input.

Summary

Each file lists its class, status, and added/removed line counts from the accepted statistics.

createOfflineBannerStore requires a probe: () => Promise<boolean> and removes showDelayMs and OFFLINE_BANNER_SHOW_DELAY_MS in favor of a fixed five-second confirmation delay.
The three-second HEAD probe to API_BASE_URL accepts every Hypertext Transfer Protocol (HTTP) response, so NetInfo alone cannot establish offline status.
Failed probes confirm offline; online reports commit immediately, while unknown reports preserve state and newer events or destruction invalidate pending results.

Files
  • apps/mobile/src/lib/offline-banner-state.ts — Source, modified (+33/−17 lines); delays the probe without changing committed state. Initial state remains unknown with isOffline: false. False results, throws, and rejections confirm offline only for a current attempt. Each source update cancels the timer and advances the generation; destruction also prevents late commits.
  • apps/mobile/src/lib/hooks/use-offline-banner-state.ts — Source, modified (+13/−1 lines); supplies the bounded reachability probe. withDeadline passes an abort signal to fetch and leaves failure handling to the store; both hooks retain one subscription.
  • apps/mobile/src/lib/offline-banner-state.test.ts — Test, modified (+203/−179 lines); revises the connectivity-store tests.
  • apps/mobile/src/lib/hooks/use-offline-banner-state.mounted.test.tsx — Test, modified (+137/−49 lines); revises the mounted connectivity-hook tests.
  • apps/mobile/src/components/offline-banner.mounted.test.tsx — Test, modified (+250/−61 lines); revises the mounted banner tests.

useRetrySecurityAgentSettings(scope) exposes retry and isRetrying for existing permission, configuration, repository, and organization-role queries without creating missing entries.
Each attempt cancels pending work, temporarily applies networkMode: 'always', retry: false, and staleTime: 0, and restores every query's options.
useSecurityAgentCapability.fetchStatus exposes paused organization requests; coordinated retries finish after all requests settle, while personal capability remains independent of organization failures.

Files
  • apps/mobile/src/lib/hooks/use-security-agent.ts — Source, modified (+57/−2 lines); adds exact-key cancellation and recovery for getPermissionStatus, getConfig, getRepositories, and their organization counterparts. Organization recovery includes organizations.list; personal fetchStatus is idle. It blocks duplicate attempts, preserves each query's error, restores options in finally, and retains cached organization roles during background errors.
  • apps/mobile/src/lib/hooks/use-security-agent.test.ts — Test, modified (+27/−7 lines); revises the Security Agent hook tests.

ScopeEntryScreen and SettingsOverviewScreen prioritize recovery for errors or deliberate retries; paused, uncached queries also qualify once connectivity becomes known.
SettingsOverviewScreen.permissionError defaults to false, allowing cached settings to show recovery across enabled states and repository modes without dropping usable data.
presentation still defaults to inline and accepts route; removing the SettingsOverviewPresentation alias changes the type declaration, not those choices.

Files
  • apps/mobile/src/components/security-agent/scope-entry-screen.tsx — Source, modified (+34/−23 lines); uses pending states to distinguish unresolved queries from missing integration and retains cached permission, configuration, and capability. It forwards permission errors and explicit retry progress. The repository query remains mounted, and setup completion uses the shared retry; recovery takes precedence over skeletons.
  • apps/mobile/src/components/security-agent/settings-overview-screen.tsx — Source, modified (+48/−40 lines); retains cached settings and expands recovery beyond disabled agents using all repositories. Known online or offline connectivity enables paused-query recovery; unavailable configuration selects the offline error, and unavailable capability selects the server error. Message priority is configuration, capability or permission, then repositories. Repository loading includes the full retry; skeletons remain the fallback, and explicit empty arrays retain the repository-selection action.
  • apps/mobile/src/components/security-agent/scope-entry-screen.test.ts — Test, modified (+261/−192 lines); revises the scope-entry tests.
  • apps/mobile/src/components/security-agent/settings-overview-screen.mounted.test.tsx — Test, modified (+264/−310 lines); revises the mounted settings overview tests.

SettingsRecoveryStatus adds an accessible recovery row with optional message and required isRetrying and onRetry inputs.
Its outlined Retry button remains present during the whole attempt, while AccessibleStatus suppresses the previous error message until the attempt ends.

Files
  • apps/mobile/src/components/security-agent/settings-recovery-status.tsx — Source, added (+36/−0 lines); combines the status with a Retry button labelled through common.retry. It passes null to the status during retries and connects the button's loading and press behavior to the required inputs.

AgentSessionListContentProps.activeSessionIds becomes a required ReadonlySet<string>, supplied through useAgentSessionListData without another query.
StoredSessionRow.live marks matching stored rows in history and search, and metaWhileLive keeps their cost and relative time visible.
Active identifiers refresh row rendering without adding active-only rows, creation controls, or a live tray; stored and search errors still govern content.

Files
  • apps/mobile/src/components/agents/use-agent-session-list-data.ts — Source, modified (+2/−0 lines); returns the existing active identifiers alongside stored and searched groups without adding active-query errors to contentIsError.
  • apps/mobile/src/components/agents/session-history-screen.tsx — Source, modified (+2/−0 lines); forwards the active identifiers and keeps empty states dependent on stored sessions, search, and filters.
  • apps/mobile/src/components/agents/session-list-content.tsx — Source, modified (+5/−1 lines); checks each session identifier for liveness and enables metadata for live rows. The shared renderer depends on the active set; session keys and the sort-based list key stay unchanged.
  • apps/mobile/src/components/agents/session-history-screen.mounted.test.tsx — Test, modified (+73/−33 lines); revises the mounted history screen tests.
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx — Test, added (+340/−0 lines); introduces mounted tests for session-list content.

SessionRowAccessibilityLabelInputs.live adds an optional, false-default opt-in to localized live speech immediately after the session title.
StoredSessionRow opts in only for live list rows, so card labels and callers without the flag retain their previous speech.
If a session needs input, that announcement wins; branch, pull request, badge, metadata, and platform speech keep their existing order.

Files
  • apps/mobile/src/components/agents/session-row-accessibility-label.ts — Source, modified (+7/−2 lines); adds the live opt-in and documents the existing examples as labels without it.
  • apps/mobile/src/components/agents/session-row.tsx — Source, modified (+3/−2 lines); enables list-only live speech and clarifies the default for callers without liveness. Visual liveness and metadata forwarding remain intact.
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts — Test, modified (+41/−0 lines); expands the session label tests.
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx — Test, added (+269/−0 lines); introduces mounted tests for stored session rows.

Tests: 10 files, with 2 additions and 8 modifications (+1,865/−831 lines): offline-banner-state.test.ts, use-offline-banner-state.mounted.test.tsx, offline-banner.mounted.test.tsx, use-security-agent.test.ts, scope-entry-screen.test.ts, settings-overview-screen.mounted.test.tsx, session-history-screen.mounted.test.tsx, session-list-content.mounted.test.tsx, session-row-accessibility-label.test.ts, session-row.mounted.test.tsx.
Generated: none (0 files).


Verification

Local end-to-end verification on an iOS simulator, 2026-09-01. Seven of nine checks passed. Two have partial coverage.

This section covers the stack's six PRs together: #5666, #5668, #5677, #5680, #5685, and #5686.

No product bug was found. No product source changed. The worktree stayed clean.

Check Result Note
A1. Cloud Agent first, then Remotes, then Terminals PASS Both group headers rendered, in that order.
A2. Each group has its own icon PASS Cloud Agent a cloud, Remotes a server, Terminals a terminal.
A3. Rows show the branch and start time, shortened and localized PASS See the shortening and locale evidence below.
A4. Matching identities each show their own short code PASS Two identical relays showed #77537b and #481fd3 on separate lines.
A5. Names and projects wrap instead of truncating PASS Verified at the largest native text size and with a long project name.
D2. The live badge survives a tab switch PASS The Agents tab kept its numeric badge on Home and Profile.
D3. The count clears when the last session exits PASS Agents showed "Nothing running right now" with no count or badge.
C. History rows show liveness PARTIAL The live dot and "JUST NOW" rendered. No nonzero session cost was established, so cost retention is unverified.
D1. Live counts are organization-scoped PARTIAL Personal scope verified. The test account exposed no organization selector, so scoped counting is untested.

Remotes and locale evidence

The installed CLI 7.5.6 reports no kind, so every real relay lands under Terminals and the Remotes group is unreachable through it. A stand-in producer therefore attached over the real CLI WebSocket contract (/api/user/cli, instanceSchema in services/session-ingest/src/types/user-connection-protocol.ts) and heartbeat an instance identity. Everything below the CLI process is the shipped path: the durable object, getConnectedInstances, activeSessions.listInstances, and the picker.

Two kind: 'remote' instances and one kind: 'cli' instance produced:

  • Grouping and order. Cloud Agent, then REMOTES with both remote rows, then TERMINALS with the terminal row.
  • Branch shortening. feature/remotes-verify1 is 23 code points and rendered as feature/remotes-veri…, exactly the documented 20-code-point boundary.
  • Missing facts stay absent. The instance with no startedAt rendered main alone, with no separator and no date.
  • Localized dates. English rendered Started Sep 1, 2026 at 7:51 AM. German rendered Gestartet 1. Sept. 2026, 07:51 — day-first, German month, 24-hour clock.
  • Localized group headings. REMOTES became REMOTE-INSTANZEN in German.
  • Accessible labels. Each row announced its group, identity, and facts together: Remotes, ci-runner-eu-west on cloud, and feature/remotes-veri… · Started Sep 1, 2026 at 7:51 AM.
  • Stable row identifiers. instance-picker-row-3c7b01, -fe6b0a, and -377bcd were byte-identical across both locales, so the identifier does not depend on displayed facts.
  • Selection. Tapping a Remotes row closed the sheet and set the control to Run on: ci-runner-eu-west · cloud.

Untested condition

The offline banner is driven only by NetInfo device connectivity. createOfflineBannerStore commits online as soon as NetInfo reports a connection and runs its HTTP probe only to suppress a false NetInfo offline report (apps/mobile/src/lib/offline-banner-state.ts:67-88). A backend-only outage with the device still online therefore shows no banner by design. A real device-wide outage was not simulated, so that path has no runtime verdict.

Setup

  • Real worktree stack (14 services) and Metro, branch mobile-ux-ad6d-s6, simulator iPhone 17 Pro on iOS 26.5.
  • Sign-in through the normal email-code screen, with the code read from the locally captured outbound email.
  • Taps and accessibility inspection through AXe. Screenshots captured with xcrun simctl io <udid> screenshot.
  • Full report and images: /Users/igor/Projects/.scratch/local-e2e-ux/.

Unrelated observation

After "Allow once" on a tool permission, repeated Back taps did not leave the chat screen; a cold restart restored navigation. Evidence: /Users/igor/Projects/.scratch/local-e2e-ux/C-back-stuck.png. None of these six PRs touch navigation, and the symptom was not reproduced in a second round. It needs a real CLI relay executing a command to reproduce, so it is recorded here rather than diagnosed.

Comment thread apps/mobile/src/components/agents/session-list-content.tsx
Comment thread apps/mobile/src/components/security-agent/settings-overview-screen.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental test-only fixture and host-query updates look correct, with high confidence and no production-code defects.

Files Reviewed (4 files)
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx
  • apps/mobile/src/components/security-agent/scope-entry-screen.test.ts
  • apps/mobile/src/components/security-agent/settings-overview-screen.mounted.test.tsx
Previous Review Summaries (4 snapshots, latest commit b3197c6)

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

Previous review (commit b3197c6)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

Visible session-history rows still miss live-status updates because SectionList extraData ignores activeSessionIds.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-list-content.tsx 175 Visible history rows will not update live status when activeSessionIds changes
Files Reviewed (21 files)
  • apps/mobile/src/components/agents/session-history-screen.mounted.test.tsx
  • apps/mobile/src/components/agents/session-history-screen.tsx
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx - 1 issue
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row-accessibility-label.ts
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/use-agent-session-list-data.ts
  • apps/mobile/src/components/offline-banner.mounted.test.tsx
  • apps/mobile/src/components/security-agent/scope-entry-screen.test.ts
  • apps/mobile/src/components/security-agent/scope-entry-screen.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.mounted.test.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.tsx
  • apps/mobile/src/components/security-agent/settings-recovery-status.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.mounted.test.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.ts
  • apps/mobile/src/lib/hooks/use-security-agent.test.ts
  • apps/mobile/src/lib/hooks/use-security-agent.ts
  • apps/mobile/src/lib/offline-banner-state.test.ts
  • apps/mobile/src/lib/offline-banner-state.ts

Fix these issues in Kilo Cloud

Previous review (commit d27a89f)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

Visible session-history rows still miss live-status updates because SectionList extraData ignores activeSessionIds.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-list-content.tsx 175 Visible history rows will not update live status when activeSessionIds changes
Files Reviewed (21 files)
  • apps/mobile/src/components/agents/session-history-screen.mounted.test.tsx
  • apps/mobile/src/components/agents/session-history-screen.tsx
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx - 1 issue
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row-accessibility-label.ts
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/use-agent-session-list-data.ts
  • apps/mobile/src/components/offline-banner.mounted.test.tsx
  • apps/mobile/src/components/security-agent/scope-entry-screen.test.ts
  • apps/mobile/src/components/security-agent/scope-entry-screen.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.mounted.test.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.tsx
  • apps/mobile/src/components/security-agent/settings-recovery-status.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.mounted.test.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.ts
  • apps/mobile/src/lib/hooks/use-security-agent.test.ts
  • apps/mobile/src/lib/hooks/use-security-agent.ts
  • apps/mobile/src/lib/offline-banner-state.test.ts
  • apps/mobile/src/lib/offline-banner-state.ts

Fix these issues in Kilo Cloud

Previous review (commit d9f0a86)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

Visible session-history rows still miss live-status updates because SectionList extraData ignores activeSessionIds.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-list-content.tsx 175 Visible history rows will not update live status when activeSessionIds changes
Files Reviewed (20 files)
  • apps/mobile/src/components/agents/session-history-screen.mounted.test.tsx
  • apps/mobile/src/components/agents/session-history-screen.tsx
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx - 1 issue
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row-accessibility-label.ts
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/use-agent-session-list-data.ts
  • apps/mobile/src/components/offline-banner.mounted.test.tsx
  • apps/mobile/src/components/security-agent/scope-entry-screen.test.ts
  • apps/mobile/src/components/security-agent/scope-entry-screen.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.mounted.test.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.mounted.test.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.ts
  • apps/mobile/src/lib/hooks/use-security-agent.test.ts
  • apps/mobile/src/lib/hooks/use-security-agent.ts
  • apps/mobile/src/lib/offline-banner-state.test.ts
  • apps/mobile/src/lib/offline-banner-state.ts

Fix these issues in Kilo Cloud

Previous review (commit 4353740)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-list-content.tsx 175 Visible history rows will not update live status when activeSessionIds changes
apps/mobile/src/components/security-agent/settings-overview-screen.tsx 95 Retry cannot recover a NetInfo-paused settings query after a successful probe
Files Reviewed (15 files)
  • apps/mobile/src/components/agents/session-history-screen.mounted.test.tsx
  • apps/mobile/src/components/agents/session-history-screen.tsx
  • apps/mobile/src/components/agents/session-list-content.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx - 1 issue
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row-accessibility-label.ts
  • apps/mobile/src/components/agents/session-row.mounted.test.tsx
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/use-agent-session-list-data.ts
  • apps/mobile/src/components/offline-banner.mounted.test.tsx
  • apps/mobile/src/components/security-agent/settings-overview-screen.tsx - 1 issue
  • apps/mobile/src/lib/hooks/use-offline-banner-state.mounted.test.tsx
  • apps/mobile/src/lib/hooks/use-offline-banner-state.ts
  • apps/mobile/src/lib/offline-banner-state.test.ts
  • apps/mobile/src/lib/offline-banner-state.ts

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 163.8K · Output: 13K · Cached: 417.3K

Review guidance: REVIEW.md from base branch mobile-ux-ad6d-s2

@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 1, 2026
@iscekic
iscekic merged commit 350af79 into main Sep 1, 2026
25 of 45 checks passed
@iscekic
iscekic deleted the mobile-ux-ad6d-s3 branch September 1, 2026 11:01
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.

2 participants