Skip to content

fix(mobile): give a lost agent connection one transcript state - #9416

Open
iscekic wants to merge 9 commits into
mainfrom
drain/session-connection-lost-one-state
Open

iscekic wants to merge 9 commits into
mainfrom
drain/session-connection-lost-one-state

Conversation

@iscekic

@iscekic iscekic commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence

Evidence: demonstrated — on emulator-5554 at the default text size and density against the local dev stack, in the fixture session ses_00000000000LiveCliStream01 with its transcript stalled: the body now shows the retryable card with its Retry instead of the skeleton and a Connection lost line in the same frame, the reserved read-only footer paints its note line and button bar in the one gray that stands off the footer's own fill (46 px and 126 px, the footer's own 17.5 dp line box and 48 dp action floor), and the header pill's value row holds the width its values take — 40.0 dp, one bar filling it while the open loads, the same row once it settles — so the pill is 97.9 dp while loading and 97.1 dp settled, where the merge base 2b4f203d3c paints a bare 51.0 dp ring in the loading frame.

Problem

The session screen had no single owner for a lost agent transport:

  • resolveSessionTerminalError only treated a status indicator of type error as the body's failure, and the SDK's own lost-transport code (agent-connection-lost) carried catalog copy instead of a class, so the classifier called it unknown: copy written for an unknown load failure and no Retry.
  • An indicator carrying that code with any other type resolved no body failure at all, so the skeleton kept painting while the footer row added Connection lost in the same frame — a loading state and a failure on one screen.
  • Once the body did state the failure, the fixed footer row and the composer reason restated it (The session could not be loaded. Retry first. beside Send), so one failure was stated twice with one meaning.

Five defects of the same window survived that change, and the design review named them across its successive reviews:

  • While the open still had nothing to show, the screen painted an editable Message composer beside the loading skeleton, even though the session's own transport had not answered and the composer was not usable. A read-only session then replaced that composer with the read-only footer, so one screen showed writing controls the session did not have and then jumped to the state it did.
  • The header context pill collapsed to a bare ring in that window and grew its value only when usage arrived, so it read as broken beside the pill the same screen shows once loaded.
  • The reserved footer painted as an empty tinted block: its bars kept the shared Skeleton's default fill, and the theme's muted equals the secondary fill of the footer the area stands in for, so the two bars painted the container's own colour.
  • The header pill painted a second dash in its cost slot while the session opened. The dash read as missing data rather than as loading, and it was narrower than the cost that replaces it, so the pill grew a value out of a smaller pill.
  • The same window still painted one real dash beside a loading bar in that row, which reads as half-painted content rather than as one placeholder. The value row is one bar while it loads and one bar per value once it settles.

Change

  • apps/mobile/src/components/agents/session-terminal-error.ts
    • The SDK's lost-transport code resolves to a retryable terminal failure whatever type its indicator carries: title Couldn't load this session, message Connection trouble. Please retry in a moment., Retry. No new copy; both strings already exist in every mobile locale.
    • isRetryableTerminalFailure answers true for that code, so the other surfaces agree.
    • The resolver takes a connectionLost fact for the app-wide transport leg, which counts only while the open still has nothing to show.
  • apps/mobile/src/components/agents/session-detail-content.tsx
    • The terminal error is resolved once, before the footer rows, and handed to the body (precedence unchanged: terminal error, then slow-load, then skeleton).
    • While the body states a failure, the fixed footer status row and the composer reason stay silent: one failure, one statement, one Retry. The composer stays mounted and editable.
    • The bottom slot belongs to the session. While the open has nothing to show and no failure, agent status or pending ask means the session has already spoken, the slot holds the read-only footer's area instead of a composer whose session may not exist. The composer keeps its place behind blocking cards and failures, and a read-only transcript still replaces it with the Continue section.
    • A loaded transcript keeps its rows, its footer status line and its sheet Retry; an empty session that already settled keeps its empty state.
  • apps/mobile/src/components/agents/session-detail-skeleton.tsx
    • The placeholder bubbles can shrink into a body shorter than they are instead of overflowing it, so a placeholder can never be sliced by the row below it.
    • SessionReadOnlyFooterPlaceholder holds the read-only footer's area — its container, a line and a button bar at the footer's own child sizes — so the footer lands on its own geometry instead of replacing a composer.
    • Its bars take bg-muted-soft, the one gray that differs from the bg-secondary fill the area reserves, so the reserved area reads as loading instead of as an empty block.
  • apps/mobile/src/components/agents/context-usage-display.ts
    • A session that has not reported usage yet keeps both value slots of the header pill, instead of collapsing to a bare ring; only the accessibility label names usage unavailable once the session has settled.
    • The cost slot states what it paints: the cost label, the dashes the values will replace, or nothing. The width no longer depends on which value the session ends up reporting, so no state grows or shrinks the pill.
    • While the open still loads, the row's two dashes keep their layout and the cost slot is marked loading, which the screen paints as one bar over that row; after the change a dash beside a bar no longer reads as half-painted content.
  • apps/mobile/src/components/agents/session-context-metrics.tsx
    • The loading row paints invisible and one bg-muted-soft bar fills a full-bleed box over it, so the placeholder takes the settled row's own text metrics at any font scale instead of a width of its own.
    • That box centres the bar in the row rather than naming a vertical inset, because the row's height follows the font too. The value row renders when either it or the cost slot has content.
  • Tests: session-terminal-error.test.ts covers the lost code on every indicator type and the app-wide leg, plus the loaded-transcript exemption; session-detail-content.test.ts covers the reported frame (skeleton replaced by one retryable card, no footer line, no send reason), the rewritten footer expectations, and the bottom slot (held area with no composer, then the read-only footer on that same frame); context-usage-display.test.ts and session-context-metrics.test.ts cover the dash-marked slots and the single loading bar that replaces the dash while the row loads; session-detail-skeleton.test.ts pins the reserved footer's geometry and the fill that stands off it, and fails if a bar goes back to the container's own colour.

Verification

  • npx vitest run src/components/agents/ in apps/mobile: 294 files, 5258 tests pass.
  • pnpm --filter kilo-app run typecheck: clean. oxlint (apps/mobile/.oxlintrc.json) and oxfmt: clean on every changed file.
  • Device, emulator-5554 at the default text size and density, local dev stack, fixture session ses_00000000000LiveCliStream01:
    • merge base 2b4f203d3c: the open's loading frame, in all four design-gate cells, paints the Message composer with mic and send and a 51.0 dp context ring; the session then settles read-only with the This is a read-only session footer and Continue, and the composer is replaced by it.
    • reviewed head 14f4a7f594: the same loading frame paints the reserved footer area (no composer) and a 78.1 dp pill with both value slots, but the reserved footer's two bars and the pill's second dash are indistinguishable from their own surfaces.
    • this head 630f55d95: with the API held for 20 s so the loading window can be captured frame by frame, the reserved footer paints two bars — 46 px of note line and 126 px of button floor — and the pill holds a 73 px cost bar at the baseline of its dash. With the API refused, the same screen settles into the retryable failure with the dash in that same slot, and the pill keeps its width (97.1 dp / 97.5 dp / 97.9 dp; frame measurements in ## Evidence).
    • this head 2581362723: the loading frame paints no dash. In all four cells the value row is 40.0 dp and the bar fills it — [346.3, 93.0, 40.0, 7.2] inside the row at [346.3, 89.5, 40.0, 14.1], vertically centred, mirrored to [25.5, 93.0] in the Arabic cell. The pill is 97.9 dp while loading and 97.1 dp once the open settles with its cost (— 8.4 dp at [910, 235], $0.40 27.4 dp at [941, 235]), where the merge base's same frame is a 51.0 dp ring.
  • Mounted reproduction of the reported frame: before the change a stalled open with a connection-lost indicator renders the skeleton and the Connection lost line; after it, neither — the retryable card with its Retry instead. Covered for indicator types error, info, progress and warning, and for an exhausted app-wide transport leg.
  • Design gate: 4 cells, 0 errors, 0 warnings.
    • At 2581362723, on the agent chat session route for the dev fixture session: every cell clean (this run is the head run uploaded for this commit).
    • The merge-base run of the same link, taken in the same session after switching the checkout to 2b4f203d3c and reloading the app: 4 cells, 0 errors and its four pre-existing VoiceInputButton touch-target warnings, which this head does not paint because its loading frame carries no composer.

Limitations

The exact dark cell from the reporting run also needs the socket to close while the transcript fetch is still pending. In the local stack both ride port 8800, so a stopped worker fails the fetch first (the error-atom state) and a dropped port hangs both: that split cannot be staged on this VM. The indicator path is therefore proved in the mounted suite, and the device run covers the loading, the read-only and the load-error states.

The design gate's default observation window closes the cell before this fixture's transcript settles, so the runs above show either the first painted frame or the loading frame; the settled read-only frame was measured on the same device with a longer observation window (--observe-ms 7000), which also reports the transcript's own scroll-in as layout-shift errors on the merge base and on this branch alike. The loading frame in the runs above is the gate's own capture right after the link opens, while this fixture's transcript is still unresolved; an earlier head held that window open with a delayed API instead, and that capture also showed the app's own slow-load card once the delay outlasted its threshold.

Production prerequisites

None.

Proxy answers

The owner's proxy gave these answers in the owner's place.

  1. Question: Fix shape: Measured on this VM: a stalled open (0 messages) with a lost agent transport paints the loading skeleton and a 'Connection lost' line in the same frame, and with a real error-type indicator the body instead shows 'Couldn't load this session / Failed to load session details' with NO Retry (the SDK's own connection-lost code falls into the 'unknown' class). Which shape do you want?
    Answer: Both: retryable error for a lost transport AND a non-clipping skeleton for ordinary loading
    Confidence: 0.55 · Precedent: Fix the root cause and the class of the issue: "if anything repeats the same mistake over and over again, fix the class" (00eb2a1d3e4b)
  2. Question: Retry on lost: A lost agent connection currently lands in the terminal-error classifier as 'unknown' (copy aimed at an unknown load failure, no Retry). Should it become a retryable transient failure?
    Answer: Yes: transient class, existing 'Connection trouble' copy, Retry present
    Confidence: 0.80 · Precedent: Reuse as much as possible of the current implementation: "reuse as much as possible from the current impl" (0a2b68365a4b); plans cover the retryable-error state (df491946927a)
  3. Question: One statement: When the body already states the failure, the fixed footer status row and the composer reason repeat it (measured: the error card plus 'The session could not be loaded. Retry first.' beside send). Suppress them?
    Answer: Suppress both while the body states the failure
    Confidence: 0.70 · Precedent: Remove redundant copy and keep surfaces consistent: "go make the public dashboard a delight to use" (0e57ea66f95b); best-in-class mobile UX (00eb2a1d3e4b)
  4. Question: App-wide leg: The app-wide socket leg can be exhausted while the session transcript is still loading (no SDK status atom at all). Should that also replace a stalled skeleton with the retryable error?
    Answer: Yes, while the transcript is still loading
    Confidence: 0.60 · Precedent: Fix the class on every affected variant: "fix this for all shared services model pickers on all surfaces" (75f8833fe8c1)
  5. Question: Loading pill: The design critic's last finding is not pre-existing: the merge base paints the pill as a bare ring (51.0 dp, no dash, no bar), and this head paints ring + '—' + a 27.8 dp skeleton bar (97.9 dp). Fix it now, or leave it and let the owner decide?
    Answer: Fix: hide the dash while loading, one bar spanning the 40.2 dp value row
    Confidence: 0.85 · Precedent: UX rule 'Stop mobile design and UX defects before they land, with a design gate': session 6341f41c09ab, owner wrote 'I very often have design/ux fixes sessions - I don't want to have those'. Also, pushing after an approval is fine: session df491946927a, 'you can push after an approval without issue'.

The session screen could paint the loading skeleton and a Connection lost
line in the same frame, with the last skeleton bubble sliced by the row, and
the load-error card restated the same failure again beside Send.

A lost agent transport now owns the body: the SDK's own connection-lost code
resolves to a retryable terminal failure with the existing connection-trouble
copy and Retry, whatever type the status indicator carries, and an exhausted
app-wide transport leg does the same while the open still has nothing to
show. While the body states a failure, the fixed footer row and the composer
reason stay silent, so one failure is stated once with the Retry that
resolves it. The skeleton's bubbles can shrink instead of overflowing a body
shorter than they are.
@iscekic iscekic added drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer labels Nov 1, 2026
@iscekic

iscekic commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Device proof on the Android emulator against the local dev stack, with the session-ingest worker stopped so the session open fails.

Before the change the load-error card and the composer reason state the same failure twice; after the change the card states it once with its Retry and no footer row.

Design gate contact sheet for the four standard cells (0 errors, 4 pre-existing touch-target warnings).

Load error before the change

Load error after the change

Design gate contact sheet

@kilo-code-bot

kilo-code-bot Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit replaces the fixed-width w-11 placeholder with a full-row overlay over the reserved dash row, so the loading bar now inherits the settled text metrics; no correctness, security, or performance defect was found in the four changed files.

Assumptions: [INFERENCE] I did not run the mobile test suite, typecheck, lint, or the design gate in this read-only session. On Android the placeholder row is hidden with importantForAccessibility="no" on the wrapper, which does not itself hide descendants; whether TalkBack still exposes the invisible primary — text was not verified on a device.

Files Reviewed (4 files)
  • apps/mobile/src/components/agents/context-usage-display.ts
  • apps/mobile/src/components/agents/context-usage-display.test.ts
  • apps/mobile/src/components/agents/session-context-metrics.tsx
  • apps/mobile/src/components/agents/session-context-metrics.test.ts
Previous Review Summaries (8 snapshots, latest commit 81d14cf)

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

Previous review (commit 81d14cf)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The incremental commit paints the loading value slot as one bar; its only new concern is that the fixed w-11 bar matches the settled dash row only at the default font scale.

Assumptions: [INFERENCE] I did not run the mobile test suite or the design gate in this read-only session; the finding rests on the app's 14 px rem spacing scale and on the shared Text primitive scaling with the live system font scale.

Overview

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

SUGGESTION

File Line Issue
apps/mobile/src/components/agents/session-context-metrics.tsx 107 The fixed w-11 loading bar equals the settled — ${dash} row only at font scale 1, so the pill can still change width at settle on non-default font scales.
Files Reviewed (4 files)
  • apps/mobile/src/components/agents/context-usage-display.ts - 0 issues
  • apps/mobile/src/components/agents/context-usage-display.test.ts - 0 issues
  • apps/mobile/src/components/agents/session-context-metrics.tsx - 1 issue
  • apps/mobile/src/components/agents/session-context-metrics.test.ts - 0 issues

Previous review (commit 630f55d)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The only change since the last review removes the export modifier from the module-local PillCostSlot type; it has no other references in apps/mobile, so nothing breaks.

Assumptions: [INFERENCE] The full pnpm typecheck and check:unused were not run in this read-only session; the safety conclusion rests on a repository-wide grep showing PillCostSlot is referenced only inside context-usage-display.ts.

Files Reviewed (1 file)
  • apps/mobile/src/components/agents/context-usage-display.ts

Previous review (commit 924a3c1)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (4 files)
  • apps/mobile/src/components/agents/context-usage-display.ts
  • apps/mobile/src/components/agents/context-usage-display.test.ts
  • apps/mobile/src/components/agents/session-context-metrics.tsx
  • apps/mobile/src/components/agents/session-context-metrics.test.ts

Previous review (commit cd4741e)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The incremental commit cd4741e58e makes the reserved loading slots visible (bg-muted-soft bars, a w-8 cost bar), but the cost bar is wider than the dash it becomes once the open settles without usage, so the header pill now shrinks ~19 dp on the empty/failure path where it previously held its width.

Assumptions: [INFERENCE] (1) the fixed-width cost bar has no shrink/min-w-0, unlike the cost Text it replaces, so on a header narrower than ~104 dp the pill could overflow; not reproduced, and the gate's compact cell reports 0 errors. (2) The route-level loading screen still reserves the composer-shaped SessionComposerSkeleton (apps/mobile/src/app/(app)/agent-chat/[session-id].tsx:295) while SessionDetailContent reserves the taller read-only footer placeholder, so the bottom slot changes height at that handoff; unchanged code, not measured in this run. (3) With an empty open the pill stays visible and pressable while its accessibilityLabel is still empty, so the loading pill is announced as an unlabeled button (the new bar is hidden from assistive tech); that logic is unchanged by this commit. Suite results and device/design-gate runs were not re-executed here; findings are from code and the PR's own measurements.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-context-metrics.tsx 110 w-8 reserves ~28 dp while loading, but costPending only holds during loading; once the open settles with no usage (empty read-only session, or the load-error frame) the slot becomes the narrow — dash, shrinking the pill ~19 dp at settle on a path that previously did not move.
Files Reviewed (6 files)
  • apps/mobile/src/components/agents/context-usage-display.ts - 0 issues
  • apps/mobile/src/components/agents/context-usage-display.test.ts - 0 issues
  • apps/mobile/src/components/agents/session-context-metrics.tsx - 1 issue
  • apps/mobile/src/components/agents/session-context-metrics.test.ts - 0 issues
  • apps/mobile/src/components/agents/session-detail-skeleton.tsx - 0 issues
  • apps/mobile/src/components/agents/session-detail-skeleton.test.ts - 0 issues

The earlier retryWith finding on session-terminal-error.ts is resolved at this head: session-owned agent-connection-lost indicators reopen the session, and only the exhausted app-wide leg uses connection.

Previous review (commit 14f4a7f)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit 14f4a7f59 reserves the bottom slot with a read-only-shaped placeholder while an empty open resolves, and gives the context pill two dash-marked value slots before usage arrives; both match their updated tests, and no new correctness or security issue was found on the changed lines.

Assumptions: [INFERENCE] two layout concerns are unproven and were not reproduced: (1) the route-level loading screen still reserves the composer-shaped SessionComposerSkeleton (apps/mobile/src/app/(app)/agent-chat/[session-id].tsx:295) while SessionDetailContent now reserves the taller read-only footer geometry, so the bottom slot changes height at that handoff; (2) during a pending open the pill renders two visible em dashes while its accessibilityLabel is empty (no context info, no cost), which a screen reader may read from the children as "dash dash". The PR's design-gate run reports 0 errors at this head.

Files Reviewed (6 files)
  • apps/mobile/src/components/agents/context-usage-display.ts
  • apps/mobile/src/components/agents/context-usage-display.test.ts
  • apps/mobile/src/components/agents/session-context-metrics.test.ts
  • apps/mobile/src/components/agents/session-detail-content.tsx
  • apps/mobile/src/components/agents/session-detail-content.test.ts
  • apps/mobile/src/components/agents/session-detail-skeleton.tsx

Scope note: the incremental commit also adds the pill's dash slots and SessionReadOnlyFooterPlaceholder, neither of which the PR description's Change section covers; the description was not re-checked against them.

Previous review (commit bd993bf)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commit bd993bfc81 splits the lost-transport Retry by cause — agent-connection-lost indicators now reopen the session while only the exhausted app-wide leg resets the shared socket — resolving the prior WARNING; both branches are asserted in the mounted suite and the resolver/target lines match current code.

Assumptions: [INFERENCE] runtime reconnect behaviour of switchSession versus connection.retryConnection() was verified from the SDK sources and the PR's mounted tests, not from a device run of the session-owned loss path.

Files Reviewed (3 files)
  • apps/mobile/src/components/agents/session-terminal-error.ts
  • apps/mobile/src/components/agents/session-terminal-error.test.ts
  • apps/mobile/src/components/agents/session-detail-content.test.ts

Resolved since the previous review: the shared retryWith: 'connection' on the session's own agent-connection-lost indicator (now 'session'), and the app-wide leg correctly keeps 'connection' so the spent reconnect budget is actually cleared.

Previous review (commit 1cd5ee4)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The skeleton and app-wide Retry fixes land correctly, but the new retryWith: 'connection' applies to the session's own agent-connection-lost indicator too, so a lost cloud-agent transport now retries the unrelated shared user-web socket instead of reopening the session.

Assumptions: [INFERENCE] the cloud-agent reachability of agent-connection-lost (empty open, transport disconnect) was verified from SDK code (cloud-agent-transport.ts, status-indicator.ts, session-manager.ts), not from a device run.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-terminal-error.ts 208 connectionLostFailure sets retryWith: 'connection' for both the app-wide leg and the session's own agent-connection-lost indicator; a lost cloud-agent transport needs switchSession, not the shared user-web retry.
Files Reviewed (5 files)
  • apps/mobile/src/components/agents/session-terminal-error.ts - 1 issue
  • apps/mobile/src/components/agents/session-detail-content.tsx - 0 issues
  • apps/mobile/src/components/agents/session-detail-skeleton.tsx - 0 issues (previous flex-item finding fixed: bubbles are now the list's flex items with shrink, container has overflow-hidden)
  • apps/mobile/src/components/agents/session-terminal-error.test.ts - 0 issues
  • apps/mobile/src/components/agents/session-detail-content.test.ts - 0 issues

Fix these issues in Kilo Cloud

Previous review (commit 06e4594)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The session-state consolidation is sound, but the skeleton shrink change cannot prevent the described clipping, and the new app-wide "connection lost" Retry re-opens over the same exhausted socket instead of restoring it.

Assumptions: [INFERENCE] the rounded dialog/error card behavior on the app-wide leg was verified only from the SDK reconnect code (user-web-connection.ts, base-connection.ts), not from a device run; the skeleton finding is based on React Native/Yoga flex semantics (the bubble is not the overflowing flex item) and was not measured on a device in this review.

Overview

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

WARNING

File Line Issue
apps/mobile/src/components/agents/session-detail-skeleton.tsx 46 shrink sits on the Skeleton, but the overflowing flex item is the auto-height row wrapper, so the bubble cannot compress and the clipping this PR targets can still occur (also lines 49, 52).
apps/mobile/src/components/agents/session-terminal-error.ts 412 The app-wide exhausted leg becomes a terminal error whose only action is manager.switchSession; only connection.retryConnection()/retryReconnect() resets the reconnect budget, so this new Retry cannot recover the socket.
Files Reviewed (5 files)
  • apps/mobile/src/components/agents/session-terminal-error.ts - 1 issue
  • apps/mobile/src/components/agents/session-detail-content.tsx - 0 issues
  • apps/mobile/src/components/agents/session-detail-skeleton.tsx - 1 issue
  • apps/mobile/src/components/agents/session-terminal-error.test.ts - 0 issues
  • apps/mobile/src/components/agents/session-detail-content.test.ts - 0 issues

Fix these issues in Kilo Cloud


Reviewed by deepseek-flash-latest · Input: 66.5K · Output: 12.8K · Cached: 688.9K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Nov 1, 2026
Two review findings on the lost-connection state.

The skeleton rows were the flex items that overflowed, and each bubble sat in
an auto-height wrapper, so flexShrink on the bubble could not reduce anything.
The bubbles are now the list's own flex items, each with its margin and
alignment, and the container clips, so a body shorter than the placeholder
compresses the shapes instead of letting one be sliced.

A spent reconnect budget is only cleared by resetting the shared transport
leg, so the terminal error now carries which recovery its Retry runs:
reopening the session for a failure the session reported, and the connection
retry for a lost leg.
@iscekic iscekic removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Nov 1, 2026
@iscekic

iscekic commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Re-ran the design gate at the new head and added the placeholder capture.

  • Design gate: 4 cells, 0 errors, 4 warnings (the pre-existing voice-input touch target on every cell; the merge-base run reports the same four).
  • Placeholder: with the app's metadata read stalled, the three placeholder bubbles keep their 3/4, 1/2 and 2/3 widths, sit above the composer, and end 11 dp above the body's bottom edge — nothing is sliced.

Design gate contact sheet at the new head

Placeholder while the session is still loading

@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Nov 1, 2026
The recovery a lost transport's Retry runs depends on which transport it was:
a session whose own transport dropped reopens, while the shared app-wide leg
needs its spent reconnect budget reset. Pass the action per branch instead of
returning the connection retry for both.
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Nov 1, 2026
@iscekic iscekic added the merge:blocked:design-review Design review has not cleared this change label Nov 1, 2026
While a session transcript was still loading, the screen painted an
editable Message composer at the bottom. The open's transport has not
answered in that window, so a read-only session replaced that composer
with the read-only footer as soon as it resolved: one screen showing
writing controls it did not have, then a jump to the state it did have.

The bottom slot is now the session's own. Until the transcript resolves —
and while no failure, agent status or pending ask means the session has
already spoken — the slot holds the read-only footer's area, at the
footer's own geometry, so the footer lands where the placeholder was.
The composer keeps its place behind blocking cards and failures.

The header context pill showed a bare ring in that same window, then grew
its value when usage arrived. A session that has not reported usage now
keeps both value slots, marked with the dash, so the pill fills the slots
it already showed instead of changing shape late.
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Nov 1, 2026
@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Nov 1, 2026
The type names this module's own selector output; nothing outside it reads it,
and the repository's unused-export check rejects it while it is exported.
@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:blocked:human-design The owner reviews the design and removed merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head labels Nov 1, 2026
@iscekic

iscekic commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

bot: The automatic design review hands this pull request to the owner at head 630f55d.
These findings still block it after the automatic fix runs:

  • base / app-agent-chat-ses-00000000000liveclistream01, the cost pill in the header, right of the title: While loading, the pill shows the real "–" separator between the spinner ring and the gray cost placeholder bar, so it reads as half-rendered content rather than a clean skeleton. Fix: Hide the "–" separator while the cost loads and let a single skeleton bar fill the space that "– $0.40" will take.
    The owner proxy could not decide it: The only remaining finding is the cost pill's loading separator, and it was captured on the base screenshot. It already exists on main, so this PR did not introduce it. No finding shows a regression in the transcript-state change at head, so the PR can merge with it.
    Send it back with these fixes, accept the design, or close it.

@iscekic iscekic removed the merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. label Nov 1, 2026
@iscekic iscekic added merge:blocked:insufficient-e2e Verification does not cover the change merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. labels Nov 1, 2026
@iscekic

iscekic commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Design gate at 81d14cfdf on the agent chat session route for the dev fixture session, matrix standard, emulator at the default text size and density.

  • this head: 4 cells, 0 errors, 0 warnings — the value row of the header pill paints as one skeleton bar with no dash beside it.
  • merge base 2b4f203d3c, same link: 4 cells, 0 errors and its four pre-existing composer voice-control touch-target warnings.

Measured in the same run from the cell dumps: the loading pill is 96.4 dp in every cell (a 28.2 dp ring and one 38.5 dp bar), the settled pill with a reported cost is 97.1 dp, and the merge base's loading frame is a bare 51.0 dp ring.

Agent chat session while the transcript loads, at this head

Agent chat session while the transcript loads, at the merge base

@iscekic iscekic removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. merge:blocked:insufficient-e2e Verification does not cover the change labels Nov 1, 2026
@iscekic

iscekic commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

bot: Design gate re-run for head 2581362723 on the agent chat session route for the dev fixture session, matrix standard, emulator at the default text size and density.

  • this head: 4 cells, 0 errors, 0 warnings.
  • merge base 2b4f203d3c, same link (fresh run after switching the checkout and reloading the app): 4 cells, 0 errors, 4 warnings — the composer voice control's pre-existing touch target, which this head does not paint because its loading frame carries no composer.

The loading value row now takes the settled row's own width instead of a fixed one. Measured in the same run: the row is 40.0 dp, the bar fills it at [346.3, 93.0, 40.0, 7.2] inside [346.3, 89.5, 40.0, 14.1] (centred), the pill is 97.9 dp while loading and 97.1 dp settled, and the Arabic cell mirrors the bar to [25.5, 93.0].

Agent chat session while the transcript loads, at this head

Agent chat session while the transcript loads, at the merge base

@iscekic iscekic added merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change merge:bot Bot-owned review; merge when ready once readiness passes and a review approves. and removed merge:blocked:kilobot-not-ready Review bot has not recommended merge at this head merge:blocked:insufficient-e2e Verification does not cover the change labels Nov 1, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

drain Work item from the findings drain explorer:android Finding surfaced by the Android explorer merge:blocked:design-review Design review has not cleared this change merge:blocked:human-design The owner reviews the design merge:bot Bot-owned review; merge when ready once readiness passes and a review approves.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants